diff options
Diffstat (limited to 'ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c')
-rw-r--r-- | ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c | 1115 |
1 files changed, 0 insertions, 1115 deletions
diff --git a/ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c b/ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c deleted file mode 100644 index 402db97a80..0000000000 --- a/ArmVirtPkg/Library/PlatformIntelBdsLib/QemuKernel.c +++ /dev/null @@ -1,1115 +0,0 @@ -/** @file
- Try to load an EFI-stubbed ARM Linux kernel from QEMU's fw_cfg.
-
- This implementation differs from OvmfPkg/Library/LoadLinuxLib. An EFI
- stub in the subject kernel is a hard requirement here.
-
- Copyright (C) 2014, Red Hat, Inc.
-
- This program and the accompanying materials are licensed and made available
- under the terms and conditions of the BSD License which accompanies this
- distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-**/
-
-#include <Guid/FileInfo.h>
-#include <Guid/FileSystemInfo.h>
-#include <Guid/FileSystemVolumeLabelInfo.h>
-#include <Library/PrintLib.h>
-#include <Library/QemuFwCfgLib.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/LoadedImage.h>
-#include <Protocol/SimpleFileSystem.h>
-
-#include "IntelBdsPlatform.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.
-//
-
-/**
- Download the kernel, the initial ramdisk, and the kernel command line from
- QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two
- image files, and load and start the kernel from it.
-
- The kernel will be instructed via its command line to load the initrd from
- the same Simple FileSystem.
-
- @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.
-
- @return Error codes from any of the underlying
- functions. On success, the function doesn't
- return.
-**/
-EFI_STATUS
-EFIAPI
-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 */);
- 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));
- goto FreeKernelDevicePath;
- }
-
- //
- // 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=<name>' 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.
- //
- EfiSignalEventReadyToBoot();
-
- //
- // Start the image.
- //
- Status = gBS->StartImage (
- KernelImageHandle,
- NULL, // ExitDataSize
- NULL // ExitData
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "%a: StartImage(): %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;
- }
- }
-
- return Status;
-}
|