From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.81]) by mx.groups.io with SMTP id smtpd.web09.10320.1583402502904725230 for ; Thu, 05 Mar 2020 02:01:43 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=TiYX5NjG; spf=pass (domain: redhat.com, ip: 207.211.31.81, mailfrom: lersek@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583402502; 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=7+ViNL6rhdHRJEgZFtBeIq9ruMcW1MrYaAqIUhchdww=; b=TiYX5NjG53VWCb9bQXml/X5YQh8j5Ms0rjblCf3FI0gsfRKzy1YzFOBY7MRkHegCxMd1fk R9HfPIe5CLgBrTmZoFHyrSsU1bdMajHkTuzBlslNifjAp9zDK2ARtwwPnqLFhv+PRnZr1Z hTtPlaAgU8i/tk8Z3+KZETaCR7PlNyI= 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-427-_DmJuOrpOC64vKVizfFR_A-1; Thu, 05 Mar 2020 05:01:40 -0500 X-MC-Unique: _DmJuOrpOC64vKVizfFR_A-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0CCF8108443F; Thu, 5 Mar 2020 10:01: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 76E7228990; Thu, 5 Mar 2020 10:01:36 +0000 (UTC) Subject: Re: [edk2-devel] [PATCH v2 06/14] ArmVirtPkg/PlatformBootManagerLib: switch to separate QEMU loader To: devel@edk2.groups.io, ard.biesheuvel@linaro.org References: <20200304095233.21046-1-ard.biesheuvel@linaro.org> <20200304095233.21046-7-ard.biesheuvel@linaro.org> From: "Laszlo Ersek" Message-ID: <55629ce8-f016-d6bb-b0e6-c3739bb9d2cc@redhat.com> Date: Thu, 5 Mar 2020 11:01:35 +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-7-ard.biesheuvel@linaro.org> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit On 03/04/20 10:52, Ard Biesheuvel wrote: > Drop the QEMU loader file system implementation inside this library, > and switch to the separate QemuLoadImageLib library and the associated > driver to expose the kernel and initrd passed via the QEMU command line. > > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2566 > Signed-off-by: Ard Biesheuvel > --- > ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 9 +- > ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c | 1061 +------------------- > 2 files changed, 7 insertions(+), 1063 deletions(-) Reviewed-by: Laszlo Ersek Thanks, Laszlo > diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > index a9d4888d4377..a010564527b6 100644 > --- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > +++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf > @@ -44,9 +44,8 @@ [LibraryClasses] > MemoryAllocationLib > PcdLib > PlatformBmPrintScLib > - PrintLib > QemuBootOrderLib > - QemuFwCfgLib > + QemuLoadImageLib > ReportStatusCodeLib > UefiBootManagerLib > UefiBootServicesTableLib > @@ -64,18 +63,12 @@ [Pcd] > gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut > > [Guids] > - gEfiFileInfoGuid > - gEfiFileSystemInfoGuid > - gEfiFileSystemVolumeLabelInfoIdGuid > gEfiEndOfDxeEventGroupGuid > gRootBridgesConnectedEventGroupGuid > gUefiShellFileGuid > > [Protocols] > - gEfiDevicePathProtocolGuid > gEfiFirmwareVolume2ProtocolGuid > gEfiGraphicsOutputProtocolGuid > - gEfiLoadedImageProtocolGuid > gEfiPciRootBridgeIoProtocolGuid > - gEfiSimpleFileSystemProtocolGuid > gVirtioDeviceProtocolGuid > diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c b/ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c > index d3851fd75fa5..e9c110a0ed75 100644 > --- a/ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c > +++ b/ArmVirtPkg/Library/PlatformBootManagerLib/QemuKernel.c > @@ -9,887 +9,11 @@ > SPDX-License-Identifier: BSD-2-Clause-Patent > **/ > > -#include > -#include > -#include > -#include > -#include > +#include > #include > -#include > -#include > -#include > > #include "PlatformBm.h" > > -// > -// Static data that hosts the fw_cfg blobs and serves file requests. > -// > -typedef enum { > - KernelBlobTypeKernel, > - KernelBlobTypeInitrd, > - KernelBlobTypeCommandLine, > - KernelBlobTypeMax > -} KERNEL_BLOB_TYPE; > - > -typedef struct { > - FIRMWARE_CONFIG_ITEM CONST SizeKey; > - FIRMWARE_CONFIG_ITEM CONST DataKey; > - CONST CHAR16 * CONST Name; > - UINT32 Size; > - UINT8 *Data; > -} KERNEL_BLOB; > - > -STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = { > - { QemuFwCfgItemKernelSize, QemuFwCfgItemKernelData, L"kernel" }, > - { QemuFwCfgItemInitrdSize, QemuFwCfgItemInitrdData, L"initrd" }, > - { QemuFwCfgItemCommandLineSize, QemuFwCfgItemCommandLineData, L"cmdline" } > -}; > - > -STATIC UINT64 mTotalBlobBytes; > - > -// > -// Device path for the handle that incorporates our "EFI stub filesystem". The > -// GUID is arbitrary and need not be standardized or advertized. > -// > -#pragma pack(1) > -typedef struct { > - VENDOR_DEVICE_PATH VenHwNode; > - EFI_DEVICE_PATH_PROTOCOL EndNode; > -} SINGLE_VENHW_NODE_DEVPATH; > -#pragma pack() > - > -STATIC CONST SINGLE_VENHW_NODE_DEVPATH mFileSystemDevicePath = { > - { > - { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH) } }, > - { > - 0xb0fae7e7, 0x6b07, 0x49d0, > - { 0x9e, 0x5b, 0x3b, 0xde, 0xc8, 0x3b, 0x03, 0x9d } > - } > - }, > - > - { > - END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, > - { sizeof (EFI_DEVICE_PATH_PROTOCOL) } > - } > -}; > - > -// > -// The "file in the EFI stub filesystem" abstraction. > -// > -STATIC EFI_TIME mInitTime; > - > -#define STUB_FILE_SIG SIGNATURE_64 ('S', 'T', 'U', 'B', 'F', 'I', 'L', 'E') > - > -typedef struct { > - UINT64 Signature; // Carries STUB_FILE_SIG. > - > - KERNEL_BLOB_TYPE BlobType; // Index into mKernelBlob. KernelBlobTypeMax > - // denotes the root directory of the filesystem. > - > - UINT64 Position; // Byte position for regular files; > - // next directory entry to return for the root > - // directory. > - > - EFI_FILE_PROTOCOL File; // Standard protocol interface. > -} STUB_FILE; > - > -#define STUB_FILE_FROM_FILE(FilePointer) \ > - CR (FilePointer, STUB_FILE, File, STUB_FILE_SIG) > - > -// > -// Tentative definition of the file protocol template. The initializer > -// (external definition) will be provided later. > -// > -STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate; > - > - > -// > -// Protocol member functions for File. > -// > - > -/** > - Opens a new file relative to the source file's location. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is > - the file handle to the source location. This would > - typically be an open handle to a directory. > - > - @param[out] NewHandle A pointer to the location to return the opened handle > - for the new file. > - > - @param[in] FileName The Null-terminated string of the name of the file to > - be opened. The file name may contain the following > - path modifiers: "\", ".", and "..". > - > - @param[in] OpenMode The mode to open the file. The only valid > - combinations that the file may be opened with are: > - Read, Read/Write, or Create/Read/Write. > - > - @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case > - these are the attribute bits for the newly created > - file. > - > - @retval EFI_SUCCESS The file was opened. > - @retval EFI_NOT_FOUND The specified file could not be found on the > - device. > - @retval EFI_NO_MEDIA The device has no medium. > - @retval EFI_MEDIA_CHANGED The device has a different medium in it or the > - medium is no longer supported. > - @retval EFI_DEVICE_ERROR The device reported an error. > - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > - @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a > - file for write when the media is > - write-protected. > - @retval EFI_ACCESS_DENIED The service denied access to the file. > - @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the > - file. > - @retval EFI_VOLUME_FULL The volume is full. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileOpen ( > - IN EFI_FILE_PROTOCOL *This, > - OUT EFI_FILE_PROTOCOL **NewHandle, > - IN CHAR16 *FileName, > - IN UINT64 OpenMode, > - IN UINT64 Attributes > - ) > -{ > - CONST STUB_FILE *StubFile; > - UINTN BlobType; > - STUB_FILE *NewStubFile; > - > - // > - // We're read-only. > - // > - switch (OpenMode) { > - case EFI_FILE_MODE_READ: > - break; > - > - case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: > - case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE: > - return EFI_WRITE_PROTECTED; > - > - default: > - return EFI_INVALID_PARAMETER; > - } > - > - // > - // Only the root directory supports opening files in it. > - // > - StubFile = STUB_FILE_FROM_FILE (This); > - if (StubFile->BlobType != KernelBlobTypeMax) { > - return EFI_UNSUPPORTED; > - } > - > - // > - // Locate the file. > - // > - for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) { > - if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) { > - break; > - } > - } > - if (BlobType == KernelBlobTypeMax) { > - return EFI_NOT_FOUND; > - } > - > - // > - // Found it. > - // > - NewStubFile = AllocatePool (sizeof *NewStubFile); > - if (NewStubFile == NULL) { > - return EFI_OUT_OF_RESOURCES; > - } > - > - NewStubFile->Signature = STUB_FILE_SIG; > - NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType; > - NewStubFile->Position = 0; > - CopyMem (&NewStubFile->File, &mEfiFileProtocolTemplate, > - sizeof mEfiFileProtocolTemplate); > - *NewHandle = &NewStubFile->File; > - > - return EFI_SUCCESS; > -} > - > - > -/** > - Closes a specified file handle. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file > - handle to close. > - > - @retval EFI_SUCCESS The file was closed. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileClose ( > - IN EFI_FILE_PROTOCOL *This > - ) > -{ > - FreePool (STUB_FILE_FROM_FILE (This)); > - return EFI_SUCCESS; > -} > - > - > -/** > - Close and delete the file handle. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the > - handle to the file to delete. > - > - @retval EFI_SUCCESS The file was closed and deleted, and the > - handle was closed. > - @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not > - deleted. > - > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileDelete ( > - IN EFI_FILE_PROTOCOL *This > - ) > -{ > - FreePool (STUB_FILE_FROM_FILE (This)); > - return EFI_WARN_DELETE_FAILURE; > -} > - > - > -/** > - Helper function that formats an EFI_FILE_INFO structure into the > - user-allocated buffer, for any valid KERNEL_BLOB_TYPE value (including > - KernelBlobTypeMax, which stands for the root directory). > - > - The interface follows the EFI_FILE_GET_INFO -- and for directories, the > - EFI_FILE_READ -- interfaces. > - > - @param[in] BlobType The KERNEL_BLOB_TYPE value identifying the fw_cfg > - blob backing the STUB_FILE that information is > - being requested about. If BlobType equals > - KernelBlobTypeMax, then information will be > - provided about the root directory of the > - filesystem. > - > - @param[in,out] BufferSize On input, the size of Buffer. On output, the > - amount of data returned in Buffer. In both cases, > - the size is measured in bytes. > - > - @param[out] Buffer A pointer to the data buffer to return. The > - buffer's type is EFI_FILE_INFO. > - > - @retval EFI_SUCCESS The information was returned. > - @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to store the > - EFI_FILE_INFO structure. BufferSize has been > - updated with the size needed to complete the > - request. > -**/ > -STATIC > -EFI_STATUS > -ConvertKernelBlobTypeToFileInfo ( > - IN KERNEL_BLOB_TYPE BlobType, > - IN OUT UINTN *BufferSize, > - OUT VOID *Buffer > - ) > -{ > - CONST CHAR16 *Name; > - UINT64 FileSize; > - UINT64 Attribute; > - > - UINTN NameSize; > - UINTN FileInfoSize; > - EFI_FILE_INFO *FileInfo; > - UINTN OriginalBufferSize; > - > - if (BlobType == KernelBlobTypeMax) { > - // > - // getting file info about the root directory > - // > - Name = L"\\"; > - FileSize = KernelBlobTypeMax; > - Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; > - } else { > - CONST KERNEL_BLOB *Blob; > - > - Blob = &mKernelBlob[BlobType]; > - Name = Blob->Name; > - FileSize = Blob->Size; > - Attribute = EFI_FILE_READ_ONLY; > - } > - > - NameSize = (StrLen(Name) + 1) * 2; > - FileInfoSize = OFFSET_OF (EFI_FILE_INFO, FileName) + NameSize; > - ASSERT (FileInfoSize >= sizeof *FileInfo); > - > - OriginalBufferSize = *BufferSize; > - *BufferSize = FileInfoSize; > - if (OriginalBufferSize < *BufferSize) { > - return EFI_BUFFER_TOO_SMALL; > - } > - > - FileInfo = (EFI_FILE_INFO *)Buffer; > - FileInfo->Size = FileInfoSize; > - FileInfo->FileSize = FileSize; > - FileInfo->PhysicalSize = FileSize; > - FileInfo->Attribute = Attribute; > - > - CopyMem (&FileInfo->CreateTime, &mInitTime, sizeof mInitTime); > - CopyMem (&FileInfo->LastAccessTime, &mInitTime, sizeof mInitTime); > - CopyMem (&FileInfo->ModificationTime, &mInitTime, sizeof mInitTime); > - CopyMem (FileInfo->FileName, Name, NameSize); > - > - return EFI_SUCCESS; > -} > - > - > -/** > - Reads data from a file, or continues scanning a directory. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that > - is the file handle to read data from. > - > - @param[in,out] BufferSize On input, the size of the Buffer. On output, the > - amount of data returned in Buffer. In both cases, > - the size is measured in bytes. If the read goes > - beyond the end of the file, the read length is > - truncated to the end of the file. > - > - If This is a directory, the function reads the > - directory entry at the current position and > - returns the entry (as EFI_FILE_INFO) in Buffer. If > - there are no more directory entries, the > - BufferSize is set to zero on output. > - > - @param[out] Buffer The buffer into which the data is read. > - > - @retval EFI_SUCCESS Data was read. > - @retval EFI_NO_MEDIA The device has no medium. > - @retval EFI_DEVICE_ERROR The device reported an error. > - @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted > - file. > - @retval EFI_DEVICE_ERROR On entry, the current file position is beyond > - the end of the file. > - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > - @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the > - current directory entry as a EFI_FILE_INFO > - structure. BufferSize has been updated with the > - size needed to complete the request, and the > - directory position has not been advanced. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileRead ( > - IN EFI_FILE_PROTOCOL *This, > - IN OUT UINTN *BufferSize, > - OUT VOID *Buffer > - ) > -{ > - STUB_FILE *StubFile; > - CONST KERNEL_BLOB *Blob; > - UINT64 Left; > - > - StubFile = STUB_FILE_FROM_FILE (This); > - > - // > - // Scanning the root directory? > - // > - if (StubFile->BlobType == KernelBlobTypeMax) { > - EFI_STATUS Status; > - > - if (StubFile->Position == KernelBlobTypeMax) { > - // > - // Scanning complete. > - // > - *BufferSize = 0; > - return EFI_SUCCESS; > - } > - > - Status = ConvertKernelBlobTypeToFileInfo ( > - (KERNEL_BLOB_TYPE)StubFile->Position, > - BufferSize, > - Buffer); > - if (EFI_ERROR (Status)) { > - return Status; > - } > - > - ++StubFile->Position; > - return EFI_SUCCESS; > - } > - > - // > - // Reading a file. > - // > - Blob = &mKernelBlob[StubFile->BlobType]; > - if (StubFile->Position > Blob->Size) { > - return EFI_DEVICE_ERROR; > - } > - > - Left = Blob->Size - StubFile->Position; > - if (*BufferSize > Left) { > - *BufferSize = (UINTN)Left; > - } > - if (Blob->Data != NULL) { > - CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize); > - } > - StubFile->Position += *BufferSize; > - return EFI_SUCCESS; > -} > - > - > -/** > - Writes data to a file. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that > - is the file handle to write data to. > - > - @param[in,out] BufferSize On input, the size of the Buffer. On output, the > - amount of data actually written. In both cases, > - the size is measured in bytes. > - > - @param[in] Buffer The buffer of data to write. > - > - @retval EFI_SUCCESS Data was written. > - @retval EFI_UNSUPPORTED Writes to open directory files are not > - supported. > - @retval EFI_NO_MEDIA The device has no medium. > - @retval EFI_DEVICE_ERROR The device reported an error. > - @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file. > - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > - @retval EFI_WRITE_PROTECTED The file or medium is write-protected. > - @retval EFI_ACCESS_DENIED The file was opened read only. > - @retval EFI_VOLUME_FULL The volume is full. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileWrite ( > - IN EFI_FILE_PROTOCOL *This, > - IN OUT UINTN *BufferSize, > - IN VOID *Buffer > - ) > -{ > - STUB_FILE *StubFile; > - > - StubFile = STUB_FILE_FROM_FILE (This); > - return (StubFile->BlobType == KernelBlobTypeMax) ? > - EFI_UNSUPPORTED : > - EFI_WRITE_PROTECTED; > -} > - > - > -/** > - Returns a file's current position. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the > - file handle to get the current position on. > - > - @param[out] Position The address to return the file's current position > - value. > - > - @retval EFI_SUCCESS The position was returned. > - @retval EFI_UNSUPPORTED The request is not valid on open directories. > - @retval EFI_DEVICE_ERROR An attempt was made to get the position from a > - deleted file. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileGetPosition ( > - IN EFI_FILE_PROTOCOL *This, > - OUT UINT64 *Position > - ) > -{ > - STUB_FILE *StubFile; > - > - StubFile = STUB_FILE_FROM_FILE (This); > - if (StubFile->BlobType == KernelBlobTypeMax) { > - return EFI_UNSUPPORTED; > - } > - > - *Position = StubFile->Position; > - return EFI_SUCCESS; > -} > - > - > -/** > - Sets a file's current position. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the > - file handle to set the requested position on. > - > - @param[in] Position The byte position from the start of the file to set. For > - regular files, MAX_UINT64 means "seek to end". For > - directories, zero means "rewind directory scan". > - > - @retval EFI_SUCCESS The position was set. > - @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open > - directories. > - @retval EFI_DEVICE_ERROR An attempt was made to set the position of a > - deleted file. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileSetPosition ( > - IN EFI_FILE_PROTOCOL *This, > - IN UINT64 Position > - ) > -{ > - STUB_FILE *StubFile; > - KERNEL_BLOB *Blob; > - > - StubFile = STUB_FILE_FROM_FILE (This); > - > - if (StubFile->BlobType == KernelBlobTypeMax) { > - if (Position == 0) { > - // > - // rewinding a directory scan is allowed > - // > - StubFile->Position = 0; > - return EFI_SUCCESS; > - } > - return EFI_UNSUPPORTED; > - } > - > - // > - // regular file seek > - // > - Blob = &mKernelBlob[StubFile->BlobType]; > - if (Position == MAX_UINT64) { > - // > - // seek to end > - // > - StubFile->Position = Blob->Size; > - } else { > - // > - // absolute seek from beginning -- seeking past the end is allowed > - // > - StubFile->Position = Position; > - } > - return EFI_SUCCESS; > -} > - > - > -/** > - Returns information about a file. > - > - @param[in] This A pointer to the EFI_FILE_PROTOCOL instance > - that is the file handle the requested > - information is for. > - > - @param[in] InformationType The type identifier GUID for the information > - being requested. The following information > - types are supported, storing the > - corresponding structures in Buffer: > - > - - gEfiFileInfoGuid: EFI_FILE_INFO > - > - - gEfiFileSystemInfoGuid: > - EFI_FILE_SYSTEM_INFO > - > - - gEfiFileSystemVolumeLabelInfoIdGuid: > - EFI_FILE_SYSTEM_VOLUME_LABEL > - > - @param[in,out] BufferSize On input, the size of Buffer. On output, the > - amount of data returned in Buffer. In both > - cases, the size is measured in bytes. > - > - @param[out] Buffer A pointer to the data buffer to return. The > - buffer's type is indicated by > - InformationType. > - > - @retval EFI_SUCCESS The information was returned. > - @retval EFI_UNSUPPORTED The InformationType is not known. > - @retval EFI_NO_MEDIA The device has no medium. > - @retval EFI_DEVICE_ERROR The device reported an error. > - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > - @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the > - information structure requested by > - InformationType. BufferSize has been updated > - with the size needed to complete the request. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileGetInfo ( > - IN EFI_FILE_PROTOCOL *This, > - IN EFI_GUID *InformationType, > - IN OUT UINTN *BufferSize, > - OUT VOID *Buffer > - ) > -{ > - CONST STUB_FILE *StubFile; > - UINTN OriginalBufferSize; > - > - StubFile = STUB_FILE_FROM_FILE (This); > - > - if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { > - return ConvertKernelBlobTypeToFileInfo (StubFile->BlobType, BufferSize, > - Buffer); > - } > - > - OriginalBufferSize = *BufferSize; > - > - if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { > - EFI_FILE_SYSTEM_INFO *FileSystemInfo; > - > - *BufferSize = sizeof *FileSystemInfo; > - if (OriginalBufferSize < *BufferSize) { > - return EFI_BUFFER_TOO_SMALL; > - } > - > - FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer; > - FileSystemInfo->Size = sizeof *FileSystemInfo; > - FileSystemInfo->ReadOnly = TRUE; > - FileSystemInfo->VolumeSize = mTotalBlobBytes; > - FileSystemInfo->FreeSpace = 0; > - FileSystemInfo->BlockSize = 1; > - FileSystemInfo->VolumeLabel[0] = L'\0'; > - > - return EFI_SUCCESS; > - } > - > - if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { > - EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel; > - > - *BufferSize = sizeof *FileSystemVolumeLabel; > - if (OriginalBufferSize < *BufferSize) { > - return EFI_BUFFER_TOO_SMALL; > - } > - > - FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer; > - FileSystemVolumeLabel->VolumeLabel[0] = L'\0'; > - > - return EFI_SUCCESS; > - } > - > - return EFI_UNSUPPORTED; > -} > - > - > -/** > - Sets information about a file. > - > - @param[in] File A pointer to the EFI_FILE_PROTOCOL instance that > - is the file handle the information is for. > - > - @param[in] InformationType The type identifier for the information being > - set. > - > - @param[in] BufferSize The size, in bytes, of Buffer. > - > - @param[in] Buffer A pointer to the data buffer to write. The > - buffer's type is indicated by InformationType. > - > - @retval EFI_SUCCESS The information was set. > - @retval EFI_UNSUPPORTED The InformationType is not known. > - @retval EFI_NO_MEDIA The device has no medium. > - @retval EFI_DEVICE_ERROR The device reported an error. > - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > - @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_INFO_ID and the > - media is read-only. > - @retval EFI_WRITE_PROTECTED InformationType is > - EFI_FILE_PROTOCOL_SYSTEM_INFO_ID and the media > - is read only. > - @retval EFI_WRITE_PROTECTED InformationType is > - EFI_FILE_SYSTEM_VOLUME_LABEL_ID and the media > - is read-only. > - @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file > - to a file that is already present. > - @retval EFI_ACCESS_DENIED An attempt is being made to change the > - EFI_FILE_DIRECTORY Attribute. > - @retval EFI_ACCESS_DENIED An attempt is being made to change the size of > - a directory. > - @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the > - file was opened read-only and an attempt is > - being made to modify a field other than > - Attribute. > - @retval EFI_VOLUME_FULL The volume is full. > - @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type > - indicated by InformationType. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileSetInfo ( > - IN EFI_FILE_PROTOCOL *This, > - IN EFI_GUID *InformationType, > - IN UINTN BufferSize, > - IN VOID *Buffer > - ) > -{ > - return EFI_WRITE_PROTECTED; > -} > - > - > -/** > - Flushes all modified data associated with a file to a device. > - > - @param [in] This A pointer to the EFI_FILE_PROTOCOL instance that is the > - file handle to flush. > - > - @retval EFI_SUCCESS The data was flushed. > - @retval EFI_NO_MEDIA The device has no medium. > - @retval EFI_DEVICE_ERROR The device reported an error. > - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > - @retval EFI_WRITE_PROTECTED The file or medium is write-protected. > - @retval EFI_ACCESS_DENIED The file was opened read-only. > - @retval EFI_VOLUME_FULL The volume is full. > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileFlush ( > - IN EFI_FILE_PROTOCOL *This > - ) > -{ > - return EFI_WRITE_PROTECTED; > -} > - > -// > -// External definition of the file protocol template. > -// > -STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = { > - EFI_FILE_PROTOCOL_REVISION, // revision 1 > - StubFileOpen, > - StubFileClose, > - StubFileDelete, > - StubFileRead, > - StubFileWrite, > - StubFileGetPosition, > - StubFileSetPosition, > - StubFileGetInfo, > - StubFileSetInfo, > - StubFileFlush, > - NULL, // OpenEx, revision 2 > - NULL, // ReadEx, revision 2 > - NULL, // WriteEx, revision 2 > - NULL // FlushEx, revision 2 > -}; > - > - > -// > -// Protocol member functions for SimpleFileSystem. > -// > - > -/** > - Open the root directory on a volume. > - > - @param[in] This A pointer to the volume to open the root directory on. > - > - @param[out] Root A pointer to the location to return the opened file handle > - for the root directory in. > - > - @retval EFI_SUCCESS The device was opened. > - @retval EFI_UNSUPPORTED This volume does not support the requested file > - system type. > - @retval EFI_NO_MEDIA The device has no medium. > - @retval EFI_DEVICE_ERROR The device reported an error. > - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. > - @retval EFI_ACCESS_DENIED The service denied access to the file. > - @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of > - resources. > - @retval EFI_MEDIA_CHANGED The device has a different medium in it or the > - medium is no longer supported. Any existing > - file handles for this volume are no longer > - valid. To access the files on the new medium, > - the volume must be reopened with OpenVolume(). > -**/ > -STATIC > -EFI_STATUS > -EFIAPI > -StubFileSystemOpenVolume ( > - IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, > - OUT EFI_FILE_PROTOCOL **Root > - ) > -{ > - STUB_FILE *StubFile; > - > - StubFile = AllocatePool (sizeof *StubFile); > - if (StubFile == NULL) { > - return EFI_OUT_OF_RESOURCES; > - } > - > - StubFile->Signature = STUB_FILE_SIG; > - StubFile->BlobType = KernelBlobTypeMax; > - StubFile->Position = 0; > - CopyMem (&StubFile->File, &mEfiFileProtocolTemplate, > - sizeof mEfiFileProtocolTemplate); > - *Root = &StubFile->File; > - > - return EFI_SUCCESS; > -} > - > -STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = { > - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, > - StubFileSystemOpenVolume > -}; > - > - > -// > -// Utility functions. > -// > - > -/** > - Populate a blob in mKernelBlob. > - > - param[in,out] Blob Pointer to the KERNEL_BLOB element in mKernelBlob that is > - to be filled from fw_cfg. > - > - @retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a > - size of zero for the blob, then Blob->Data has > - been left unchanged. > - > - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for Blob->Data. > -**/ > -STATIC > -EFI_STATUS > -FetchBlob ( > - IN OUT KERNEL_BLOB *Blob > - ) > -{ > - UINT32 Left; > - > - // > - // Read blob size. > - // > - QemuFwCfgSelectItem (Blob->SizeKey); > - Blob->Size = QemuFwCfgRead32 (); > - if (Blob->Size == 0) { > - return EFI_SUCCESS; > - } > - > - // > - // Read blob. > - // > - Blob->Data = AllocatePool (Blob->Size); > - if (Blob->Data == NULL) { > - DEBUG ((EFI_D_ERROR, "%a: failed to allocate %Ld bytes for \"%s\"\n", > - __FUNCTION__, (INT64)Blob->Size, Blob->Name)); > - return EFI_OUT_OF_RESOURCES; > - } > - > - DEBUG ((EFI_D_INFO, "%a: loading %Ld bytes for \"%s\"\n", __FUNCTION__, > - (INT64)Blob->Size, Blob->Name)); > - QemuFwCfgSelectItem (Blob->DataKey); > - > - Left = Blob->Size; > - do { > - UINT32 Chunk; > - > - Chunk = (Left < SIZE_1MB) ? Left : SIZE_1MB; > - QemuFwCfgReadBytes (Chunk, Blob->Data + (Blob->Size - Left)); > - Left -= Chunk; > - DEBUG ((EFI_D_VERBOSE, "%a: %Ld bytes remaining for \"%s\"\n", > - __FUNCTION__, (INT64)Left, Blob->Name)); > - } while (Left > 0); > - return EFI_SUCCESS; > -} > - > - > // > // The entry point of the feature. > // > @@ -916,159 +40,14 @@ TryRunningQemuKernel ( > VOID > ) > { > - UINTN BlobType; > - KERNEL_BLOB *CurrentBlob; > - KERNEL_BLOB *KernelBlob, *InitrdBlob, *CommandLineBlob; > EFI_STATUS Status; > - EFI_HANDLE FileSystemHandle; > - EFI_DEVICE_PATH_PROTOCOL *KernelDevicePath; > EFI_HANDLE KernelImageHandle; > - EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage; > > - Status = gRT->GetTime (&mInitTime, NULL /* Capabilities */); > + Status = QemuLoadKernelImage (&KernelImageHandle); > if (EFI_ERROR (Status)) { > - DEBUG ((EFI_D_ERROR, "%a: GetTime(): %r\n", __FUNCTION__, Status)); > return Status; > } > > - // > - // Fetch all blobs. > - // > - for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) { > - CurrentBlob = &mKernelBlob[BlobType]; > - Status = FetchBlob (CurrentBlob); > - if (EFI_ERROR (Status)) { > - goto FreeBlobs; > - } > - mTotalBlobBytes += CurrentBlob->Size; > - } > - KernelBlob = &mKernelBlob[KernelBlobTypeKernel]; > - InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd]; > - CommandLineBlob = &mKernelBlob[KernelBlobTypeCommandLine]; > - > - if (KernelBlob->Data == NULL) { > - Status = EFI_NOT_FOUND; > - goto FreeBlobs; > - } > - > - // > - // Create a new handle with a single VenHw() node device path protocol on it, > - // plus a custom SimpleFileSystem protocol on it. > - // > - FileSystemHandle = NULL; > - Status = gBS->InstallMultipleProtocolInterfaces (&FileSystemHandle, > - &gEfiDevicePathProtocolGuid, &mFileSystemDevicePath, > - &gEfiSimpleFileSystemProtocolGuid, &mFileSystem, > - NULL); > - if (EFI_ERROR (Status)) { > - DEBUG ((EFI_D_ERROR, "%a: InstallMultipleProtocolInterfaces(): %r\n", > - __FUNCTION__, Status)); > - goto FreeBlobs; > - } > - > - // > - // Create a device path for the kernel image to be loaded from that will call > - // back into our file system. > - // > - KernelDevicePath = FileDevicePath (FileSystemHandle, KernelBlob->Name); > - if (KernelDevicePath == NULL) { > - DEBUG ((EFI_D_ERROR, "%a: failed to allocate kernel device path\n", > - __FUNCTION__)); > - Status = EFI_OUT_OF_RESOURCES; > - goto UninstallProtocols; > - } > - > - // > - // Load the image. This should call back into our file system. > - // > - Status = gBS->LoadImage ( > - FALSE, // BootPolicy: exact match required > - gImageHandle, // ParentImageHandle > - KernelDevicePath, > - NULL, // SourceBuffer > - 0, // SourceSize > - &KernelImageHandle > - ); > - if (EFI_ERROR (Status)) { > - DEBUG ((EFI_D_ERROR, "%a: LoadImage(): %r\n", __FUNCTION__, Status)); > - if (Status != EFI_SECURITY_VIOLATION) { > - goto FreeKernelDevicePath; > - } > - // > - // From the resource allocation perspective, EFI_SECURITY_VIOLATION means > - // "success", so we must roll back the image loading. > - // > - goto UnloadKernelImage; > - } > - > - // > - // Construct the kernel command line. > - // > - Status = gBS->OpenProtocol ( > - KernelImageHandle, > - &gEfiLoadedImageProtocolGuid, > - (VOID **)&KernelLoadedImage, > - gImageHandle, // AgentHandle > - NULL, // ControllerHandle > - EFI_OPEN_PROTOCOL_GET_PROTOCOL > - ); > - ASSERT_EFI_ERROR (Status); > - > - if (CommandLineBlob->Data == NULL) { > - KernelLoadedImage->LoadOptionsSize = 0; > - } else { > - // > - // Verify NUL-termination of the command line. > - // > - if (CommandLineBlob->Data[CommandLineBlob->Size - 1] != '\0') { > - DEBUG ((EFI_D_ERROR, "%a: kernel command line is not NUL-terminated\n", > - __FUNCTION__)); > - Status = EFI_PROTOCOL_ERROR; > - goto UnloadKernelImage; > - } > - > - // > - // Drop the terminating NUL, convert to UTF-16. > - // > - KernelLoadedImage->LoadOptionsSize = (CommandLineBlob->Size - 1) * 2; > - } > - > - if (InitrdBlob->Data != NULL) { > - // > - // Append ' initrd=' in UTF-16. > - // > - KernelLoadedImage->LoadOptionsSize += > - (8 + StrLen(InitrdBlob->Name)) * 2; > - } > - > - if (KernelLoadedImage->LoadOptionsSize == 0) { > - KernelLoadedImage->LoadOptions = NULL; > - } else { > - // > - // NUL-terminate in UTF-16. > - // > - KernelLoadedImage->LoadOptionsSize += 2; > - > - KernelLoadedImage->LoadOptions = AllocatePool ( > - KernelLoadedImage->LoadOptionsSize); > - if (KernelLoadedImage->LoadOptions == NULL) { > - KernelLoadedImage->LoadOptionsSize = 0; > - Status = EFI_OUT_OF_RESOURCES; > - goto UnloadKernelImage; > - } > - > - UnicodeSPrintAsciiFormat ( > - KernelLoadedImage->LoadOptions, > - KernelLoadedImage->LoadOptionsSize, > - "%a%a%s", > - (CommandLineBlob->Data == NULL) ? "" : (CHAR8 *)CommandLineBlob->Data, > - (InitrdBlob->Data == NULL) ? "" : " initrd=", > - (InitrdBlob->Data == NULL) ? L"" : InitrdBlob->Name > - ); > - DEBUG ((EFI_D_INFO, "%a: command line: \"%s\"\n", __FUNCTION__, > - (CHAR16 *)KernelLoadedImage->LoadOptions)); > - } > - > // > // Signal the EFI_EVENT_GROUP_READY_TO_BOOT event. > // > @@ -1080,41 +59,13 @@ TryRunningQemuKernel ( > // > // Start the image. > // > - Status = gBS->StartImage ( > - KernelImageHandle, > - NULL, // ExitDataSize > - NULL // ExitData > - ); > + Status = QemuStartKernelImage (&KernelImageHandle); > if (EFI_ERROR (Status)) { > - DEBUG ((EFI_D_ERROR, "%a: StartImage(): %r\n", __FUNCTION__, Status)); > + DEBUG ((DEBUG_ERROR, "%a: QemuStartKernelImage(): %r\n", __FUNCTION__, > + Status)); > } > > - if (KernelLoadedImage->LoadOptions != NULL) { > - FreePool (KernelLoadedImage->LoadOptions); > - } > - KernelLoadedImage->LoadOptionsSize = 0; > - > -UnloadKernelImage: > - gBS->UnloadImage (KernelImageHandle); > - > -FreeKernelDevicePath: > - FreePool (KernelDevicePath); > - > -UninstallProtocols: > - gBS->UninstallMultipleProtocolInterfaces (FileSystemHandle, > - &gEfiSimpleFileSystemProtocolGuid, &mFileSystem, > - &gEfiDevicePathProtocolGuid, &mFileSystemDevicePath, > - NULL); > - > -FreeBlobs: > - while (BlobType > 0) { > - CurrentBlob = &mKernelBlob[--BlobType]; > - if (CurrentBlob->Data != NULL) { > - FreePool (CurrentBlob->Data); > - CurrentBlob->Size = 0; > - CurrentBlob->Data = NULL; > - } > - } > + QemuUnloadKernelImage (KernelImageHandle); > > return Status; > } >