mirror of https://github.com/acidanthera/audk.git
OvmfPkg/QemuKernelLoaderFsDxe: rework direct kernel boot filesystem
Split KERNEL_BLOB struct into two: * One (KERNEL_BLOB_ITEMS) static array describing how to load (unnamed) blobs from fw_cfg. * And one (KERNEL_BLOB) dynamically allocated linked list carrying the data blobs for the pseudo filesystem. Also add some debug logging. Prefix most functions with 'QemuKernel' for consistency and easier log file grepping. Add some small helper functions. This refactoring prepares for loading blobs in other ways. No (intentional) change in filesystem protocol behavior. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
139cbb266b
commit
459f5ffa24
|
@ -31,13 +31,6 @@
|
|||
//
|
||||
// Static data that hosts the fw_cfg blobs and serves file requests.
|
||||
//
|
||||
typedef enum {
|
||||
KernelBlobTypeKernel,
|
||||
KernelBlobTypeInitrd,
|
||||
KernelBlobTypeCommandLine,
|
||||
KernelBlobTypeMax
|
||||
} KERNEL_BLOB_TYPE;
|
||||
|
||||
typedef struct {
|
||||
CONST CHAR16 Name[8];
|
||||
struct {
|
||||
|
@ -45,11 +38,17 @@ typedef struct {
|
|||
FIRMWARE_CONFIG_ITEM CONST DataKey;
|
||||
UINT32 Size;
|
||||
} FwCfgItem[2];
|
||||
UINT32 Size;
|
||||
UINT8 *Data;
|
||||
} KERNEL_BLOB;
|
||||
} KERNEL_BLOB_ITEMS;
|
||||
|
||||
STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {
|
||||
typedef struct KERNEL_BLOB KERNEL_BLOB;
|
||||
struct KERNEL_BLOB {
|
||||
CHAR16 Name[8];
|
||||
UINT32 Size;
|
||||
UINT8 *Data;
|
||||
KERNEL_BLOB *Next;
|
||||
};
|
||||
|
||||
STATIC KERNEL_BLOB_ITEMS mKernelBlobItems[] = {
|
||||
{
|
||||
L"kernel",
|
||||
{
|
||||
|
@ -69,7 +68,9 @@ STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {
|
|||
}
|
||||
};
|
||||
|
||||
STATIC UINT64 mTotalBlobBytes;
|
||||
STATIC KERNEL_BLOB *mKernelBlobs;
|
||||
STATIC UINT64 mKernelBlobCount;
|
||||
STATIC UINT64 mTotalBlobBytes;
|
||||
|
||||
//
|
||||
// Device path for the handle that incorporates our "EFI stub filesystem".
|
||||
|
@ -117,7 +118,7 @@ STATIC EFI_TIME mInitTime;
|
|||
typedef struct {
|
||||
UINT64 Signature; // Carries STUB_FILE_SIG.
|
||||
|
||||
KERNEL_BLOB_TYPE BlobType; // Index into mKernelBlob. KernelBlobTypeMax
|
||||
KERNEL_BLOB *Blob; // Index into mKernelBlob. KernelBlobTypeMax
|
||||
// denotes the root directory of the filesystem.
|
||||
|
||||
UINT64 Position; // Byte position for regular files;
|
||||
|
@ -177,7 +178,7 @@ typedef struct {
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileOpen (
|
||||
QemuKernelStubFileOpen (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **NewHandle,
|
||||
IN CHAR16 *FileName,
|
||||
|
@ -196,7 +197,7 @@ StubFileOpen (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileClose (
|
||||
QemuKernelStubFileClose (
|
||||
IN EFI_FILE_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
|
@ -219,7 +220,7 @@ StubFileClose (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileDelete (
|
||||
QemuKernelStubFileDelete (
|
||||
IN EFI_FILE_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
|
@ -229,18 +230,17 @@ StubFileDelete (
|
|||
|
||||
/**
|
||||
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).
|
||||
user-allocated buffer, for any valid KERNEL_BLOB (including NULL,
|
||||
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
|
||||
@param[in] Blob The KERNEL_BLOB 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.
|
||||
being requested about. If Blob is NULL,
|
||||
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,
|
||||
|
@ -257,10 +257,10 @@ StubFileDelete (
|
|||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ConvertKernelBlobTypeToFileInfo (
|
||||
IN KERNEL_BLOB_TYPE BlobType,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer
|
||||
QemuKernelBlobTypeToFileInfo (
|
||||
IN KERNEL_BLOB *Blob,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
CONST CHAR16 *Name;
|
||||
|
@ -272,17 +272,16 @@ ConvertKernelBlobTypeToFileInfo (
|
|||
EFI_FILE_INFO *FileInfo;
|
||||
UINTN OriginalBufferSize;
|
||||
|
||||
if (BlobType == KernelBlobTypeMax) {
|
||||
if (Blob == NULL) {
|
||||
//
|
||||
// getting file info about the root directory
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "%a: file info: directory\n", __func__));
|
||||
Name = L"\\";
|
||||
FileSize = KernelBlobTypeMax;
|
||||
FileSize = mKernelBlobCount;
|
||||
Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
|
||||
} else {
|
||||
CONST KERNEL_BLOB *Blob;
|
||||
|
||||
Blob = &mKernelBlob[BlobType];
|
||||
DEBUG ((DEBUG_INFO, "%a: file info: \"%s\"\n", __func__, Blob->Name));
|
||||
Name = Blob->Name;
|
||||
FileSize = Blob->Size;
|
||||
Attribute = EFI_FILE_READ_ONLY;
|
||||
|
@ -312,6 +311,23 @@ ConvertKernelBlobTypeToFileInfo (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
KERNEL_BLOB *
|
||||
FindKernelBlob (
|
||||
CHAR16 *FileName
|
||||
)
|
||||
{
|
||||
KERNEL_BLOB *Blob;
|
||||
|
||||
for (Blob = mKernelBlobs; Blob != NULL; Blob = Blob->Next) {
|
||||
if (StrCmp (FileName, Blob->Name) == 0) {
|
||||
return Blob;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Reads data from a file, or continues scanning a directory.
|
||||
|
||||
|
@ -349,25 +365,25 @@ ConvertKernelBlobTypeToFileInfo (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileRead (
|
||||
QemuKernelStubFileRead (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
STUB_FILE *StubFile;
|
||||
CONST KERNEL_BLOB *Blob;
|
||||
UINT64 Left;
|
||||
STUB_FILE *StubFile;
|
||||
KERNEL_BLOB *Blob;
|
||||
UINT64 Left, Pos;
|
||||
|
||||
StubFile = STUB_FILE_FROM_FILE (This);
|
||||
|
||||
//
|
||||
// Scanning the root directory?
|
||||
//
|
||||
if (StubFile->BlobType == KernelBlobTypeMax) {
|
||||
if (StubFile->Blob == NULL) {
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (StubFile->Position == KernelBlobTypeMax) {
|
||||
if (StubFile->Position == mKernelBlobCount) {
|
||||
//
|
||||
// Scanning complete.
|
||||
//
|
||||
|
@ -375,8 +391,16 @@ StubFileRead (
|
|||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = ConvertKernelBlobTypeToFileInfo (
|
||||
(KERNEL_BLOB_TYPE)StubFile->Position,
|
||||
for (Pos = 0, Blob = mKernelBlobs;
|
||||
Pos < StubFile->Position;
|
||||
Pos++, Blob = Blob->Next)
|
||||
{
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: file list: #%d \"%s\"\n", __func__, Pos, Blob->Name));
|
||||
|
||||
Status = QemuKernelBlobTypeToFileInfo (
|
||||
Blob,
|
||||
BufferSize,
|
||||
Buffer
|
||||
);
|
||||
|
@ -391,7 +415,7 @@ StubFileRead (
|
|||
//
|
||||
// Reading a file.
|
||||
//
|
||||
Blob = &mKernelBlob[StubFile->BlobType];
|
||||
Blob = StubFile->Blob;
|
||||
if (StubFile->Position > Blob->Size) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
@ -402,6 +426,7 @@ StubFileRead (
|
|||
}
|
||||
|
||||
if (Blob->Data != NULL) {
|
||||
DEBUG ((DEBUG_INFO, "%a: file read: \"%s\", %d bytes\n", __func__, Blob->Name, *BufferSize));
|
||||
CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize);
|
||||
}
|
||||
|
||||
|
@ -435,7 +460,7 @@ StubFileRead (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileWrite (
|
||||
QemuKernelStubFileWrite (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN VOID *Buffer
|
||||
|
@ -444,7 +469,7 @@ StubFileWrite (
|
|||
STUB_FILE *StubFile;
|
||||
|
||||
StubFile = STUB_FILE_FROM_FILE (This);
|
||||
return (StubFile->BlobType == KernelBlobTypeMax) ?
|
||||
return (StubFile->Blob == NULL) ?
|
||||
EFI_UNSUPPORTED :
|
||||
EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
@ -466,7 +491,7 @@ StubFileWrite (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileGetPosition (
|
||||
QemuKernelStubFileGetPosition (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
OUT UINT64 *Position
|
||||
)
|
||||
|
@ -474,7 +499,7 @@ StubFileGetPosition (
|
|||
STUB_FILE *StubFile;
|
||||
|
||||
StubFile = STUB_FILE_FROM_FILE (This);
|
||||
if (StubFile->BlobType == KernelBlobTypeMax) {
|
||||
if (StubFile->Blob == NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -501,7 +526,7 @@ StubFileGetPosition (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileSetPosition (
|
||||
QemuKernelStubFileSetPosition (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN UINT64 Position
|
||||
)
|
||||
|
@ -511,7 +536,7 @@ StubFileSetPosition (
|
|||
|
||||
StubFile = STUB_FILE_FROM_FILE (This);
|
||||
|
||||
if (StubFile->BlobType == KernelBlobTypeMax) {
|
||||
if (StubFile->Blob == NULL) {
|
||||
if (Position == 0) {
|
||||
//
|
||||
// rewinding a directory scan is allowed
|
||||
|
@ -526,7 +551,7 @@ StubFileSetPosition (
|
|||
//
|
||||
// regular file seek
|
||||
//
|
||||
Blob = &mKernelBlob[StubFile->BlobType];
|
||||
Blob = StubFile->Blob;
|
||||
if (Position == MAX_UINT64) {
|
||||
//
|
||||
// seek to end
|
||||
|
@ -583,7 +608,7 @@ StubFileSetPosition (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileGetInfo (
|
||||
QemuKernelStubFileGetInfo (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN EFI_GUID *InformationType,
|
||||
IN OUT UINTN *BufferSize,
|
||||
|
@ -596,8 +621,8 @@ StubFileGetInfo (
|
|||
StubFile = STUB_FILE_FROM_FILE (This);
|
||||
|
||||
if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
|
||||
return ConvertKernelBlobTypeToFileInfo (
|
||||
StubFile->BlobType,
|
||||
return QemuKernelBlobTypeToFileInfo (
|
||||
StubFile->Blob,
|
||||
BufferSize,
|
||||
Buffer
|
||||
);
|
||||
|
@ -685,7 +710,7 @@ StubFileGetInfo (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileSetInfo (
|
||||
QemuKernelStubFileSetInfo (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
IN EFI_GUID *InformationType,
|
||||
IN UINTN BufferSize,
|
||||
|
@ -712,7 +737,7 @@ StubFileSetInfo (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileFlush (
|
||||
QemuKernelStubFileFlush (
|
||||
IN EFI_FILE_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
|
@ -724,16 +749,16 @@ StubFileFlush (
|
|||
//
|
||||
STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {
|
||||
EFI_FILE_PROTOCOL_REVISION, // revision 1
|
||||
StubFileOpen,
|
||||
StubFileClose,
|
||||
StubFileDelete,
|
||||
StubFileRead,
|
||||
StubFileWrite,
|
||||
StubFileGetPosition,
|
||||
StubFileSetPosition,
|
||||
StubFileGetInfo,
|
||||
StubFileSetInfo,
|
||||
StubFileFlush,
|
||||
QemuKernelStubFileOpen,
|
||||
QemuKernelStubFileClose,
|
||||
QemuKernelStubFileDelete,
|
||||
QemuKernelStubFileRead,
|
||||
QemuKernelStubFileWrite,
|
||||
QemuKernelStubFileGetPosition,
|
||||
QemuKernelStubFileSetPosition,
|
||||
QemuKernelStubFileGetInfo,
|
||||
QemuKernelStubFileSetInfo,
|
||||
QemuKernelStubFileFlush,
|
||||
NULL, // OpenEx, revision 2
|
||||
NULL, // ReadEx, revision 2
|
||||
NULL, // WriteEx, revision 2
|
||||
|
@ -743,7 +768,7 @@ STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileOpen (
|
||||
QemuKernelStubFileOpen (
|
||||
IN EFI_FILE_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **NewHandle,
|
||||
IN CHAR16 *FileName,
|
||||
|
@ -752,7 +777,7 @@ StubFileOpen (
|
|||
)
|
||||
{
|
||||
CONST STUB_FILE *StubFile;
|
||||
UINTN BlobType;
|
||||
KERNEL_BLOB *Blob;
|
||||
STUB_FILE *NewStubFile;
|
||||
|
||||
//
|
||||
|
@ -774,21 +799,20 @@ StubFileOpen (
|
|||
// Only the root directory supports opening files in it.
|
||||
//
|
||||
StubFile = STUB_FILE_FROM_FILE (This);
|
||||
if (StubFile->BlobType != KernelBlobTypeMax) {
|
||||
if (StubFile->Blob != NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Locate the file.
|
||||
//
|
||||
for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {
|
||||
if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Blob = FindKernelBlob (FileName);
|
||||
|
||||
if (BlobType == KernelBlobTypeMax) {
|
||||
if (Blob == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "%a: file not found: \"%s\"\n", __func__, FileName));
|
||||
return EFI_NOT_FOUND;
|
||||
} else {
|
||||
DEBUG ((DEBUG_INFO, "%a: file opened: \"%s\"\n", __func__, FileName));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -800,7 +824,7 @@ StubFileOpen (
|
|||
}
|
||||
|
||||
NewStubFile->Signature = STUB_FILE_SIG;
|
||||
NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType;
|
||||
NewStubFile->Blob = Blob;
|
||||
NewStubFile->Position = 0;
|
||||
CopyMem (
|
||||
&NewStubFile->File,
|
||||
|
@ -842,7 +866,7 @@ StubFileOpen (
|
|||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
StubFileSystemOpenVolume (
|
||||
QemuKernelStubFileSystemOpenVolume (
|
||||
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||
OUT EFI_FILE_PROTOCOL **Root
|
||||
)
|
||||
|
@ -855,7 +879,7 @@ StubFileSystemOpenVolume (
|
|||
}
|
||||
|
||||
StubFile->Signature = STUB_FILE_SIG;
|
||||
StubFile->BlobType = KernelBlobTypeMax;
|
||||
StubFile->Blob = NULL;
|
||||
StubFile->Position = 0;
|
||||
CopyMem (
|
||||
&StubFile->File,
|
||||
|
@ -869,13 +893,13 @@ StubFileSystemOpenVolume (
|
|||
|
||||
STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = {
|
||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
|
||||
StubFileSystemOpenVolume
|
||||
QemuKernelStubFileSystemOpenVolume
|
||||
};
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitrdLoadFile2 (
|
||||
QemuKernelInitrdLoadFile2 (
|
||||
IN EFI_LOAD_FILE2_PROTOCOL *This,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||
IN BOOLEAN BootPolicy,
|
||||
|
@ -883,8 +907,11 @@ InitrdLoadFile2 (
|
|||
OUT VOID *Buffer OPTIONAL
|
||||
)
|
||||
{
|
||||
CONST KERNEL_BLOB *InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd];
|
||||
KERNEL_BLOB *InitrdBlob;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a: initrd read\n", __func__));
|
||||
InitrdBlob = FindKernelBlob (L"initrd");
|
||||
ASSERT (InitrdBlob != NULL);
|
||||
ASSERT (InitrdBlob->Size > 0);
|
||||
|
||||
if (BootPolicy) {
|
||||
|
@ -913,17 +940,33 @@ InitrdLoadFile2 (
|
|||
}
|
||||
|
||||
STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {
|
||||
InitrdLoadFile2,
|
||||
QemuKernelInitrdLoadFile2,
|
||||
};
|
||||
|
||||
//
|
||||
// Utility functions.
|
||||
//
|
||||
|
||||
STATIC VOID
|
||||
QemuKernelChunkedRead (
|
||||
UINT8 *Dest,
|
||||
UINT32 Bytes
|
||||
)
|
||||
{
|
||||
UINT32 Chunk;
|
||||
|
||||
while (Bytes > 0) {
|
||||
Chunk = (Bytes < SIZE_1MB) ? Bytes : SIZE_1MB;
|
||||
QemuFwCfgReadBytes (Chunk, Dest);
|
||||
Bytes -= Chunk;
|
||||
Dest += Chunk;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Populate a blob in mKernelBlob.
|
||||
|
||||
param[in,out] Blob Pointer to the KERNEL_BLOB element in mKernelBlob that is
|
||||
param[in,out] Blob Pointer to the KERNEL_BLOB_ITEMS that is
|
||||
to be filled from fw_cfg.
|
||||
|
||||
@retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a
|
||||
|
@ -934,35 +977,46 @@ STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {
|
|||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
FetchBlob (
|
||||
IN OUT KERNEL_BLOB *Blob
|
||||
QemuKernelFetchBlob (
|
||||
IN KERNEL_BLOB_ITEMS *BlobItems
|
||||
)
|
||||
{
|
||||
UINT32 Left;
|
||||
UINTN Idx;
|
||||
UINT8 *ChunkData;
|
||||
UINT32 Size;
|
||||
UINTN Idx;
|
||||
UINT8 *ChunkData;
|
||||
KERNEL_BLOB *Blob;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Read blob size.
|
||||
//
|
||||
Blob->Size = 0;
|
||||
for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) {
|
||||
if (Blob->FwCfgItem[Idx].SizeKey == 0) {
|
||||
for (Size = 0, Idx = 0; Idx < ARRAY_SIZE (BlobItems->FwCfgItem); Idx++) {
|
||||
if (BlobItems->FwCfgItem[Idx].SizeKey == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].SizeKey);
|
||||
Blob->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();
|
||||
Blob->Size += Blob->FwCfgItem[Idx].Size;
|
||||
QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].SizeKey);
|
||||
BlobItems->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();
|
||||
Size += BlobItems->FwCfgItem[Idx].Size;
|
||||
}
|
||||
|
||||
if (Blob->Size == 0) {
|
||||
if (Size == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Blob = AllocatePool (sizeof (*Blob));
|
||||
if (Blob->Data == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ZeroMem (Blob, sizeof (*Blob));
|
||||
|
||||
//
|
||||
// Read blob.
|
||||
//
|
||||
Status = StrCpyS (Blob->Name, sizeof (Blob->Name), BlobItems->Name);
|
||||
ASSERT (!EFI_ERROR (Status));
|
||||
Blob->Size = Size;
|
||||
Blob->Data = AllocatePool (Blob->Size);
|
||||
if (Blob->Data == NULL) {
|
||||
DEBUG ((
|
||||
|
@ -972,6 +1026,7 @@ FetchBlob (
|
|||
(INT64)Blob->Size,
|
||||
Blob->Name
|
||||
));
|
||||
FreePool (Blob);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
|
@ -984,36 +1039,50 @@ FetchBlob (
|
|||
));
|
||||
|
||||
ChunkData = Blob->Data;
|
||||
for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) {
|
||||
if (Blob->FwCfgItem[Idx].DataKey == 0) {
|
||||
for (Idx = 0; Idx < ARRAY_SIZE (BlobItems->FwCfgItem); Idx++) {
|
||||
if (BlobItems->FwCfgItem[Idx].DataKey == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].DataKey);
|
||||
|
||||
Left = Blob->FwCfgItem[Idx].Size;
|
||||
while (Left > 0) {
|
||||
UINT32 Chunk;
|
||||
|
||||
Chunk = (Left < SIZE_1MB) ? Left : SIZE_1MB;
|
||||
QemuFwCfgReadBytes (Chunk, ChunkData + Blob->FwCfgItem[Idx].Size - Left);
|
||||
Left -= Chunk;
|
||||
DEBUG ((
|
||||
DEBUG_VERBOSE,
|
||||
"%a: %Ld bytes remaining for \"%s\" (%d)\n",
|
||||
__func__,
|
||||
(INT64)Left,
|
||||
Blob->Name,
|
||||
(INT32)Idx
|
||||
));
|
||||
}
|
||||
|
||||
ChunkData += Blob->FwCfgItem[Idx].Size;
|
||||
QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].DataKey);
|
||||
QemuKernelChunkedRead (ChunkData, BlobItems->FwCfgItem[Idx].Size);
|
||||
ChunkData += BlobItems->FwCfgItem[Idx].Size;
|
||||
}
|
||||
|
||||
Blob->Next = mKernelBlobs;
|
||||
mKernelBlobs = Blob;
|
||||
mKernelBlobCount++;
|
||||
mTotalBlobBytes += Blob->Size;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
QemuKernelVerifyBlob (
|
||||
CHAR16 *FileName,
|
||||
EFI_STATUS FetchStatus
|
||||
)
|
||||
{
|
||||
KERNEL_BLOB *Blob;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((StrCmp (FileName, L"kernel") != 0) &&
|
||||
(StrCmp (FileName, L"initrd") != 0) &&
|
||||
(StrCmp (FileName, L"cmdline") != 0))
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Blob = FindKernelBlob (FileName);
|
||||
Status = VerifyBlob (
|
||||
FileName,
|
||||
Blob ? Blob->Data : NULL,
|
||||
Blob ? Blob->Size : 0,
|
||||
FetchStatus
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// The entry point of the feature.
|
||||
//
|
||||
|
@ -1038,13 +1107,13 @@ QemuKernelLoaderFsDxeEntrypoint (
|
|||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
UINTN BlobType;
|
||||
KERNEL_BLOB *CurrentBlob;
|
||||
KERNEL_BLOB *KernelBlob;
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS FetchStatus;
|
||||
EFI_HANDLE FileSystemHandle;
|
||||
EFI_HANDLE InitrdLoadFile2Handle;
|
||||
UINTN BlobIdx;
|
||||
KERNEL_BLOB_ITEMS *BlobItems;
|
||||
KERNEL_BLOB *Blob;
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS FetchStatus;
|
||||
EFI_HANDLE FileSystemHandle;
|
||||
EFI_HANDLE InitrdLoadFile2Handle;
|
||||
|
||||
if (!QemuFwCfgIsAvailable ()) {
|
||||
return EFI_NOT_FOUND;
|
||||
|
@ -1059,26 +1128,22 @@ QemuKernelLoaderFsDxeEntrypoint (
|
|||
//
|
||||
// Fetch all blobs.
|
||||
//
|
||||
for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {
|
||||
CurrentBlob = &mKernelBlob[BlobType];
|
||||
FetchStatus = FetchBlob (CurrentBlob);
|
||||
for (BlobIdx = 0; BlobIdx < ARRAY_SIZE (mKernelBlobItems); ++BlobIdx) {
|
||||
BlobItems = &mKernelBlobItems[BlobIdx];
|
||||
FetchStatus = QemuKernelFetchBlob (BlobItems);
|
||||
|
||||
Status = VerifyBlob (
|
||||
CurrentBlob->Name,
|
||||
CurrentBlob->Data,
|
||||
CurrentBlob->Size,
|
||||
Status = QemuKernelVerifyBlob (
|
||||
(CHAR16 *)BlobItems->Name,
|
||||
FetchStatus
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto FreeBlobs;
|
||||
}
|
||||
|
||||
mTotalBlobBytes += CurrentBlob->Size;
|
||||
}
|
||||
|
||||
KernelBlob = &mKernelBlob[KernelBlobTypeKernel];
|
||||
|
||||
if (KernelBlob->Data == NULL) {
|
||||
Blob = FindKernelBlob (L"kernel");
|
||||
if (Blob == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "%a: no kernel present -> quit\n", __func__));
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto FreeBlobs;
|
||||
}
|
||||
|
@ -1106,7 +1171,9 @@ QemuKernelLoaderFsDxeEntrypoint (
|
|||
goto FreeBlobs;
|
||||
}
|
||||
|
||||
if (KernelBlob[KernelBlobTypeInitrd].Size > 0) {
|
||||
Blob = FindKernelBlob (L"initrd");
|
||||
if (Blob != NULL) {
|
||||
DEBUG ((DEBUG_INFO, "%a: initrd setup\n", __func__));
|
||||
InitrdLoadFile2Handle = NULL;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&InitrdLoadFile2Handle,
|
||||
|
@ -1141,13 +1208,11 @@ UninstallFileSystemHandle:
|
|||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
FreeBlobs:
|
||||
while (BlobType > 0) {
|
||||
CurrentBlob = &mKernelBlob[--BlobType];
|
||||
if (CurrentBlob->Data != NULL) {
|
||||
FreePool (CurrentBlob->Data);
|
||||
CurrentBlob->Size = 0;
|
||||
CurrentBlob->Data = NULL;
|
||||
}
|
||||
while (mKernelBlobs != NULL) {
|
||||
Blob = mKernelBlobs;
|
||||
mKernelBlobs = Blob->Next;
|
||||
FreePool (Blob->Data);
|
||||
FreePool (Blob);
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
|
Loading…
Reference in New Issue