diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index 6fe0a1bb12..11f52e019b 100644 --- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -44,9 +44,8 @@ MemoryAllocationLib PcdLib PlatformBmPrintScLib - PrintLib QemuBootOrderLib - QemuFwCfgLib + QemuLoadImageLib ReportStatusCodeLib UefiBootManagerLib UefiBootServicesTableLib @@ -64,19 +63,13 @@ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut [Guids] - gEfiFileInfoGuid - gEfiFileSystemInfoGuid - gEfiFileSystemVolumeLabelInfoIdGuid gEfiEndOfDxeEventGroupGuid gEfiGlobalVariableGuid 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 d3851fd75f..e9c110a0ed 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; }