mirror of https://github.com/acidanthera/audk.git
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 <lersek@redhat.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: James Bottomley <jejb@linux.ibm.com> Cc: Tobin Feldman-Fitzthum <tobin@linux.ibm.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3457 Signed-off-by: Dov Murik <dovmurik@linux.ibm.com> Message-Id: <20210628105110.379951-5-dovmurik@linux.ibm.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
parent
24b0e9d128
commit
cf20302474
|
@ -11,13 +11,14 @@
|
||||||
#include <Base.h>
|
#include <Base.h>
|
||||||
#include <Guid/QemuKernelLoaderFsMedia.h>
|
#include <Guid/QemuKernelLoaderFsMedia.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/FileHandleLib.h>
|
||||||
#include <Library/MemoryAllocationLib.h>
|
#include <Library/MemoryAllocationLib.h>
|
||||||
#include <Library/PrintLib.h>
|
#include <Library/PrintLib.h>
|
||||||
#include <Library/QemuFwCfgLib.h>
|
|
||||||
#include <Library/QemuLoadImageLib.h>
|
#include <Library/QemuLoadImageLib.h>
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
#include <Protocol/DevicePath.h>
|
#include <Protocol/DevicePath.h>
|
||||||
#include <Protocol/LoadedImage.h>
|
#include <Protocol/LoadedImage.h>
|
||||||
|
#include <Protocol/SimpleFileSystem.h>
|
||||||
|
|
||||||
#pragma pack (1)
|
#pragma pack (1)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -30,6 +31,11 @@ typedef struct {
|
||||||
KERNEL_FILE_DEVPATH FileNode;
|
KERNEL_FILE_DEVPATH FileNode;
|
||||||
EFI_DEVICE_PATH_PROTOCOL EndNode;
|
EFI_DEVICE_PATH_PROTOCOL EndNode;
|
||||||
} KERNEL_VENMEDIA_FILE_DEVPATH;
|
} KERNEL_VENMEDIA_FILE_DEVPATH;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VENDOR_DEVICE_PATH VenMediaNode;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL EndNode;
|
||||||
|
} SINGLE_VENMEDIA_NODE_DEVPATH;
|
||||||
#pragma pack ()
|
#pragma pack ()
|
||||||
|
|
||||||
STATIC CONST KERNEL_VENMEDIA_FILE_DEVPATH mKernelDevicePath = {
|
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
|
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
|
QEMU's fw_cfg. The kernel will be instructed via its command line to load
|
||||||
|
@ -76,12 +158,16 @@ QemuLoadKernelImage (
|
||||||
OUT EFI_HANDLE *ImageHandle
|
OUT EFI_HANDLE *ImageHandle
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_HANDLE KernelImageHandle;
|
EFI_HANDLE KernelImageHandle;
|
||||||
EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage;
|
EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage;
|
||||||
UINTN CommandLineSize;
|
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
|
||||||
CHAR8 *CommandLine;
|
EFI_HANDLE FsVolumeHandle;
|
||||||
UINTN InitrdSize;
|
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.
|
// Load the image. This should call back into the QEMU EFI loader file system.
|
||||||
|
@ -124,8 +210,38 @@ QemuLoadKernelImage (
|
||||||
);
|
);
|
||||||
ASSERT_EFI_ERROR (Status);
|
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) {
|
if (CommandLineSize == 0) {
|
||||||
KernelLoadedImage->LoadOptionsSize = 0;
|
KernelLoadedImage->LoadOptionsSize = 0;
|
||||||
|
@ -133,11 +249,14 @@ QemuLoadKernelImage (
|
||||||
CommandLine = AllocatePool (CommandLineSize);
|
CommandLine = AllocatePool (CommandLineSize);
|
||||||
if (CommandLine == NULL) {
|
if (CommandLine == NULL) {
|
||||||
Status = EFI_OUT_OF_RESOURCES;
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
goto UnloadImage;
|
goto CloseRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);
|
Status = ReadWholeQemuKernelLoaderBlob (Root, L"cmdline", CommandLineSize,
|
||||||
QemuFwCfgReadBytes (CommandLineSize, CommandLine);
|
CommandLine);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto FreeCommandLine;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Verify NUL-termination of the command line.
|
// Verify NUL-termination of the command line.
|
||||||
|
@ -155,8 +274,10 @@ QemuLoadKernelImage (
|
||||||
KernelLoadedImage->LoadOptionsSize = (UINT32)((CommandLineSize - 1) * 2);
|
KernelLoadedImage->LoadOptionsSize = (UINT32)((CommandLineSize - 1) * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize);
|
Status = GetQemuKernelLoaderBlobSize (Root, L"initrd", &InitrdSize);
|
||||||
InitrdSize = (UINTN)QemuFwCfgRead32 ();
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto FreeCommandLine;
|
||||||
|
}
|
||||||
|
|
||||||
if (InitrdSize > 0) {
|
if (InitrdSize > 0) {
|
||||||
//
|
//
|
||||||
|
@ -199,6 +320,8 @@ FreeCommandLine:
|
||||||
if (CommandLineSize > 0) {
|
if (CommandLineSize > 0) {
|
||||||
FreePool (CommandLine);
|
FreePool (CommandLine);
|
||||||
}
|
}
|
||||||
|
CloseRoot:
|
||||||
|
Root->Close (Root);
|
||||||
UnloadImage:
|
UnloadImage:
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
gBS->UnloadImage (KernelImageHandle);
|
gBS->UnloadImage (KernelImageHandle);
|
||||||
|
|
|
@ -25,14 +25,15 @@
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
DebugLib
|
DebugLib
|
||||||
|
FileHandleLib
|
||||||
MemoryAllocationLib
|
MemoryAllocationLib
|
||||||
PrintLib
|
PrintLib
|
||||||
QemuFwCfgLib
|
|
||||||
UefiBootServicesTableLib
|
UefiBootServicesTableLib
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
gEfiDevicePathProtocolGuid
|
gEfiDevicePathProtocolGuid
|
||||||
gEfiLoadedImageProtocolGuid
|
gEfiLoadedImageProtocolGuid
|
||||||
|
gEfiSimpleFileSystemProtocolGuid
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
gQemuKernelLoaderFsMediaGuid
|
gQemuKernelLoaderFsMediaGuid
|
||||||
|
|
Loading…
Reference in New Issue