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:
Gerd Hoffmann 2025-01-14 17:36:39 +01:00 committed by Ard Biesheuvel
parent 139cbb266b
commit 459f5ffa24

View File

@ -31,13 +31,6 @@
// //
// Static data that hosts the fw_cfg blobs and serves file requests. // Static data that hosts the fw_cfg blobs and serves file requests.
// //
typedef enum {
KernelBlobTypeKernel,
KernelBlobTypeInitrd,
KernelBlobTypeCommandLine,
KernelBlobTypeMax
} KERNEL_BLOB_TYPE;
typedef struct { typedef struct {
CONST CHAR16 Name[8]; CONST CHAR16 Name[8];
struct { struct {
@ -45,11 +38,17 @@ typedef struct {
FIRMWARE_CONFIG_ITEM CONST DataKey; FIRMWARE_CONFIG_ITEM CONST DataKey;
UINT32 Size; UINT32 Size;
} FwCfgItem[2]; } FwCfgItem[2];
} KERNEL_BLOB_ITEMS;
typedef struct KERNEL_BLOB KERNEL_BLOB;
struct KERNEL_BLOB {
CHAR16 Name[8];
UINT32 Size; UINT32 Size;
UINT8 *Data; UINT8 *Data;
} KERNEL_BLOB; KERNEL_BLOB *Next;
};
STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = { STATIC KERNEL_BLOB_ITEMS mKernelBlobItems[] = {
{ {
L"kernel", L"kernel",
{ {
@ -69,6 +68,8 @@ STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {
} }
}; };
STATIC KERNEL_BLOB *mKernelBlobs;
STATIC UINT64 mKernelBlobCount;
STATIC UINT64 mTotalBlobBytes; STATIC UINT64 mTotalBlobBytes;
// //
@ -117,7 +118,7 @@ STATIC EFI_TIME mInitTime;
typedef struct { typedef struct {
UINT64 Signature; // Carries STUB_FILE_SIG. 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. // denotes the root directory of the filesystem.
UINT64 Position; // Byte position for regular files; UINT64 Position; // Byte position for regular files;
@ -177,7 +178,7 @@ typedef struct {
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileOpen ( QemuKernelStubFileOpen (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle, OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName, IN CHAR16 *FileName,
@ -196,7 +197,7 @@ StubFileOpen (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileClose ( QemuKernelStubFileClose (
IN EFI_FILE_PROTOCOL *This IN EFI_FILE_PROTOCOL *This
) )
{ {
@ -219,7 +220,7 @@ StubFileClose (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileDelete ( QemuKernelStubFileDelete (
IN EFI_FILE_PROTOCOL *This IN EFI_FILE_PROTOCOL *This
) )
{ {
@ -229,18 +230,17 @@ StubFileDelete (
/** /**
Helper function that formats an EFI_FILE_INFO structure into the Helper function that formats an EFI_FILE_INFO structure into the
user-allocated buffer, for any valid KERNEL_BLOB_TYPE value (including user-allocated buffer, for any valid KERNEL_BLOB (including NULL,
KernelBlobTypeMax, which stands for the root directory). which stands for the root directory).
The interface follows the EFI_FILE_GET_INFO -- and for directories, the The interface follows the EFI_FILE_GET_INFO -- and for directories, the
EFI_FILE_READ -- interfaces. 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 blob backing the STUB_FILE that information is
being requested about. If BlobType equals being requested about. If Blob is NULL,
KernelBlobTypeMax, then information will be then information will be provided about the root
provided about the root directory of the directory of the filesystem.
filesystem.
@param[in,out] BufferSize On input, the size of Buffer. On output, the @param[in,out] BufferSize On input, the size of Buffer. On output, the
amount of data returned in Buffer. In both cases, amount of data returned in Buffer. In both cases,
@ -257,8 +257,8 @@ StubFileDelete (
**/ **/
STATIC STATIC
EFI_STATUS EFI_STATUS
ConvertKernelBlobTypeToFileInfo ( QemuKernelBlobTypeToFileInfo (
IN KERNEL_BLOB_TYPE BlobType, IN KERNEL_BLOB *Blob,
IN OUT UINTN *BufferSize, IN OUT UINTN *BufferSize,
OUT VOID *Buffer OUT VOID *Buffer
) )
@ -272,17 +272,16 @@ ConvertKernelBlobTypeToFileInfo (
EFI_FILE_INFO *FileInfo; EFI_FILE_INFO *FileInfo;
UINTN OriginalBufferSize; UINTN OriginalBufferSize;
if (BlobType == KernelBlobTypeMax) { if (Blob == NULL) {
// //
// getting file info about the root directory // getting file info about the root directory
// //
DEBUG ((DEBUG_INFO, "%a: file info: directory\n", __func__));
Name = L"\\"; Name = L"\\";
FileSize = KernelBlobTypeMax; FileSize = mKernelBlobCount;
Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
} else { } else {
CONST KERNEL_BLOB *Blob; DEBUG ((DEBUG_INFO, "%a: file info: \"%s\"\n", __func__, Blob->Name));
Blob = &mKernelBlob[BlobType];
Name = Blob->Name; Name = Blob->Name;
FileSize = Blob->Size; FileSize = Blob->Size;
Attribute = EFI_FILE_READ_ONLY; Attribute = EFI_FILE_READ_ONLY;
@ -312,6 +311,23 @@ ConvertKernelBlobTypeToFileInfo (
return EFI_SUCCESS; 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. Reads data from a file, or continues scanning a directory.
@ -349,25 +365,25 @@ ConvertKernelBlobTypeToFileInfo (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileRead ( QemuKernelStubFileRead (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize, IN OUT UINTN *BufferSize,
OUT VOID *Buffer OUT VOID *Buffer
) )
{ {
STUB_FILE *StubFile; STUB_FILE *StubFile;
CONST KERNEL_BLOB *Blob; KERNEL_BLOB *Blob;
UINT64 Left; UINT64 Left, Pos;
StubFile = STUB_FILE_FROM_FILE (This); StubFile = STUB_FILE_FROM_FILE (This);
// //
// Scanning the root directory? // Scanning the root directory?
// //
if (StubFile->BlobType == KernelBlobTypeMax) { if (StubFile->Blob == NULL) {
EFI_STATUS Status; EFI_STATUS Status;
if (StubFile->Position == KernelBlobTypeMax) { if (StubFile->Position == mKernelBlobCount) {
// //
// Scanning complete. // Scanning complete.
// //
@ -375,8 +391,16 @@ StubFileRead (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
Status = ConvertKernelBlobTypeToFileInfo ( for (Pos = 0, Blob = mKernelBlobs;
(KERNEL_BLOB_TYPE)StubFile->Position, Pos < StubFile->Position;
Pos++, Blob = Blob->Next)
{
}
DEBUG ((DEBUG_INFO, "%a: file list: #%d \"%s\"\n", __func__, Pos, Blob->Name));
Status = QemuKernelBlobTypeToFileInfo (
Blob,
BufferSize, BufferSize,
Buffer Buffer
); );
@ -391,7 +415,7 @@ StubFileRead (
// //
// Reading a file. // Reading a file.
// //
Blob = &mKernelBlob[StubFile->BlobType]; Blob = StubFile->Blob;
if (StubFile->Position > Blob->Size) { if (StubFile->Position > Blob->Size) {
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
@ -402,6 +426,7 @@ StubFileRead (
} }
if (Blob->Data != NULL) { 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); CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize);
} }
@ -435,7 +460,7 @@ StubFileRead (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileWrite ( QemuKernelStubFileWrite (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
IN OUT UINTN *BufferSize, IN OUT UINTN *BufferSize,
IN VOID *Buffer IN VOID *Buffer
@ -444,7 +469,7 @@ StubFileWrite (
STUB_FILE *StubFile; STUB_FILE *StubFile;
StubFile = STUB_FILE_FROM_FILE (This); StubFile = STUB_FILE_FROM_FILE (This);
return (StubFile->BlobType == KernelBlobTypeMax) ? return (StubFile->Blob == NULL) ?
EFI_UNSUPPORTED : EFI_UNSUPPORTED :
EFI_WRITE_PROTECTED; EFI_WRITE_PROTECTED;
} }
@ -466,7 +491,7 @@ StubFileWrite (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileGetPosition ( QemuKernelStubFileGetPosition (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
OUT UINT64 *Position OUT UINT64 *Position
) )
@ -474,7 +499,7 @@ StubFileGetPosition (
STUB_FILE *StubFile; STUB_FILE *StubFile;
StubFile = STUB_FILE_FROM_FILE (This); StubFile = STUB_FILE_FROM_FILE (This);
if (StubFile->BlobType == KernelBlobTypeMax) { if (StubFile->Blob == NULL) {
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
@ -501,7 +526,7 @@ StubFileGetPosition (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileSetPosition ( QemuKernelStubFileSetPosition (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
IN UINT64 Position IN UINT64 Position
) )
@ -511,7 +536,7 @@ StubFileSetPosition (
StubFile = STUB_FILE_FROM_FILE (This); StubFile = STUB_FILE_FROM_FILE (This);
if (StubFile->BlobType == KernelBlobTypeMax) { if (StubFile->Blob == NULL) {
if (Position == 0) { if (Position == 0) {
// //
// rewinding a directory scan is allowed // rewinding a directory scan is allowed
@ -526,7 +551,7 @@ StubFileSetPosition (
// //
// regular file seek // regular file seek
// //
Blob = &mKernelBlob[StubFile->BlobType]; Blob = StubFile->Blob;
if (Position == MAX_UINT64) { if (Position == MAX_UINT64) {
// //
// seek to end // seek to end
@ -583,7 +608,7 @@ StubFileSetPosition (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileGetInfo ( QemuKernelStubFileGetInfo (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType, IN EFI_GUID *InformationType,
IN OUT UINTN *BufferSize, IN OUT UINTN *BufferSize,
@ -596,8 +621,8 @@ StubFileGetInfo (
StubFile = STUB_FILE_FROM_FILE (This); StubFile = STUB_FILE_FROM_FILE (This);
if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
return ConvertKernelBlobTypeToFileInfo ( return QemuKernelBlobTypeToFileInfo (
StubFile->BlobType, StubFile->Blob,
BufferSize, BufferSize,
Buffer Buffer
); );
@ -685,7 +710,7 @@ StubFileGetInfo (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileSetInfo ( QemuKernelStubFileSetInfo (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
IN EFI_GUID *InformationType, IN EFI_GUID *InformationType,
IN UINTN BufferSize, IN UINTN BufferSize,
@ -712,7 +737,7 @@ StubFileSetInfo (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileFlush ( QemuKernelStubFileFlush (
IN EFI_FILE_PROTOCOL *This IN EFI_FILE_PROTOCOL *This
) )
{ {
@ -724,16 +749,16 @@ StubFileFlush (
// //
STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = { STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {
EFI_FILE_PROTOCOL_REVISION, // revision 1 EFI_FILE_PROTOCOL_REVISION, // revision 1
StubFileOpen, QemuKernelStubFileOpen,
StubFileClose, QemuKernelStubFileClose,
StubFileDelete, QemuKernelStubFileDelete,
StubFileRead, QemuKernelStubFileRead,
StubFileWrite, QemuKernelStubFileWrite,
StubFileGetPosition, QemuKernelStubFileGetPosition,
StubFileSetPosition, QemuKernelStubFileSetPosition,
StubFileGetInfo, QemuKernelStubFileGetInfo,
StubFileSetInfo, QemuKernelStubFileSetInfo,
StubFileFlush, QemuKernelStubFileFlush,
NULL, // OpenEx, revision 2 NULL, // OpenEx, revision 2
NULL, // ReadEx, revision 2 NULL, // ReadEx, revision 2
NULL, // WriteEx, revision 2 NULL, // WriteEx, revision 2
@ -743,7 +768,7 @@ STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileOpen ( QemuKernelStubFileOpen (
IN EFI_FILE_PROTOCOL *This, IN EFI_FILE_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **NewHandle, OUT EFI_FILE_PROTOCOL **NewHandle,
IN CHAR16 *FileName, IN CHAR16 *FileName,
@ -752,7 +777,7 @@ StubFileOpen (
) )
{ {
CONST STUB_FILE *StubFile; CONST STUB_FILE *StubFile;
UINTN BlobType; KERNEL_BLOB *Blob;
STUB_FILE *NewStubFile; STUB_FILE *NewStubFile;
// //
@ -774,21 +799,20 @@ StubFileOpen (
// Only the root directory supports opening files in it. // Only the root directory supports opening files in it.
// //
StubFile = STUB_FILE_FROM_FILE (This); StubFile = STUB_FILE_FROM_FILE (This);
if (StubFile->BlobType != KernelBlobTypeMax) { if (StubFile->Blob != NULL) {
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
// //
// Locate the file. // Locate the file.
// //
for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) { Blob = FindKernelBlob (FileName);
if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {
break;
}
}
if (BlobType == KernelBlobTypeMax) { if (Blob == NULL) {
DEBUG ((DEBUG_INFO, "%a: file not found: \"%s\"\n", __func__, FileName));
return EFI_NOT_FOUND; 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->Signature = STUB_FILE_SIG;
NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType; NewStubFile->Blob = Blob;
NewStubFile->Position = 0; NewStubFile->Position = 0;
CopyMem ( CopyMem (
&NewStubFile->File, &NewStubFile->File,
@ -842,7 +866,7 @@ StubFileOpen (
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
StubFileSystemOpenVolume ( QemuKernelStubFileSystemOpenVolume (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
OUT EFI_FILE_PROTOCOL **Root OUT EFI_FILE_PROTOCOL **Root
) )
@ -855,7 +879,7 @@ StubFileSystemOpenVolume (
} }
StubFile->Signature = STUB_FILE_SIG; StubFile->Signature = STUB_FILE_SIG;
StubFile->BlobType = KernelBlobTypeMax; StubFile->Blob = NULL;
StubFile->Position = 0; StubFile->Position = 0;
CopyMem ( CopyMem (
&StubFile->File, &StubFile->File,
@ -869,13 +893,13 @@ StubFileSystemOpenVolume (
STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = { STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = {
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
StubFileSystemOpenVolume QemuKernelStubFileSystemOpenVolume
}; };
STATIC STATIC
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
InitrdLoadFile2 ( QemuKernelInitrdLoadFile2 (
IN EFI_LOAD_FILE2_PROTOCOL *This, IN EFI_LOAD_FILE2_PROTOCOL *This,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
IN BOOLEAN BootPolicy, IN BOOLEAN BootPolicy,
@ -883,8 +907,11 @@ InitrdLoadFile2 (
OUT VOID *Buffer OPTIONAL 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); ASSERT (InitrdBlob->Size > 0);
if (BootPolicy) { if (BootPolicy) {
@ -913,17 +940,33 @@ InitrdLoadFile2 (
} }
STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = { STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {
InitrdLoadFile2, QemuKernelInitrdLoadFile2,
}; };
// //
// Utility functions. // 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. 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. to be filled from fw_cfg.
@retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a @retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a
@ -934,35 +977,46 @@ STATIC CONST EFI_LOAD_FILE2_PROTOCOL mInitrdLoadFile2 = {
**/ **/
STATIC STATIC
EFI_STATUS EFI_STATUS
FetchBlob ( QemuKernelFetchBlob (
IN OUT KERNEL_BLOB *Blob IN KERNEL_BLOB_ITEMS *BlobItems
) )
{ {
UINT32 Left; UINT32 Size;
UINTN Idx; UINTN Idx;
UINT8 *ChunkData; UINT8 *ChunkData;
KERNEL_BLOB *Blob;
EFI_STATUS Status;
// //
// Read blob size. // Read blob size.
// //
Blob->Size = 0; for (Size = 0, Idx = 0; Idx < ARRAY_SIZE (BlobItems->FwCfgItem); Idx++) {
for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) { if (BlobItems->FwCfgItem[Idx].SizeKey == 0) {
if (Blob->FwCfgItem[Idx].SizeKey == 0) {
break; break;
} }
QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].SizeKey); QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].SizeKey);
Blob->FwCfgItem[Idx].Size = QemuFwCfgRead32 (); BlobItems->FwCfgItem[Idx].Size = QemuFwCfgRead32 ();
Blob->Size += Blob->FwCfgItem[Idx].Size; Size += BlobItems->FwCfgItem[Idx].Size;
} }
if (Blob->Size == 0) { if (Size == 0) {
return EFI_SUCCESS; return EFI_SUCCESS;
} }
Blob = AllocatePool (sizeof (*Blob));
if (Blob->Data == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (Blob, sizeof (*Blob));
// //
// Read blob. // Read blob.
// //
Status = StrCpyS (Blob->Name, sizeof (Blob->Name), BlobItems->Name);
ASSERT (!EFI_ERROR (Status));
Blob->Size = Size;
Blob->Data = AllocatePool (Blob->Size); Blob->Data = AllocatePool (Blob->Size);
if (Blob->Data == NULL) { if (Blob->Data == NULL) {
DEBUG (( DEBUG ((
@ -972,6 +1026,7 @@ FetchBlob (
(INT64)Blob->Size, (INT64)Blob->Size,
Blob->Name Blob->Name
)); ));
FreePool (Blob);
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
} }
@ -984,36 +1039,50 @@ FetchBlob (
)); ));
ChunkData = Blob->Data; ChunkData = Blob->Data;
for (Idx = 0; Idx < ARRAY_SIZE (Blob->FwCfgItem); Idx++) { for (Idx = 0; Idx < ARRAY_SIZE (BlobItems->FwCfgItem); Idx++) {
if (Blob->FwCfgItem[Idx].DataKey == 0) { if (BlobItems->FwCfgItem[Idx].DataKey == 0) {
break; break;
} }
QemuFwCfgSelectItem (Blob->FwCfgItem[Idx].DataKey); QemuFwCfgSelectItem (BlobItems->FwCfgItem[Idx].DataKey);
QemuKernelChunkedRead (ChunkData, BlobItems->FwCfgItem[Idx].Size);
Left = Blob->FwCfgItem[Idx].Size; ChunkData += BlobItems->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;
} }
Blob->Next = mKernelBlobs;
mKernelBlobs = Blob;
mKernelBlobCount++;
mTotalBlobBytes += Blob->Size;
return EFI_SUCCESS; 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. // The entry point of the feature.
// //
@ -1038,9 +1107,9 @@ QemuKernelLoaderFsDxeEntrypoint (
IN EFI_SYSTEM_TABLE *SystemTable IN EFI_SYSTEM_TABLE *SystemTable
) )
{ {
UINTN BlobType; UINTN BlobIdx;
KERNEL_BLOB *CurrentBlob; KERNEL_BLOB_ITEMS *BlobItems;
KERNEL_BLOB *KernelBlob; KERNEL_BLOB *Blob;
EFI_STATUS Status; EFI_STATUS Status;
EFI_STATUS FetchStatus; EFI_STATUS FetchStatus;
EFI_HANDLE FileSystemHandle; EFI_HANDLE FileSystemHandle;
@ -1059,26 +1128,22 @@ QemuKernelLoaderFsDxeEntrypoint (
// //
// Fetch all blobs. // Fetch all blobs.
// //
for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) { for (BlobIdx = 0; BlobIdx < ARRAY_SIZE (mKernelBlobItems); ++BlobIdx) {
CurrentBlob = &mKernelBlob[BlobType]; BlobItems = &mKernelBlobItems[BlobIdx];
FetchStatus = FetchBlob (CurrentBlob); FetchStatus = QemuKernelFetchBlob (BlobItems);
Status = VerifyBlob ( Status = QemuKernelVerifyBlob (
CurrentBlob->Name, (CHAR16 *)BlobItems->Name,
CurrentBlob->Data,
CurrentBlob->Size,
FetchStatus FetchStatus
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto FreeBlobs; goto FreeBlobs;
} }
mTotalBlobBytes += CurrentBlob->Size;
} }
KernelBlob = &mKernelBlob[KernelBlobTypeKernel]; Blob = FindKernelBlob (L"kernel");
if (Blob == NULL) {
if (KernelBlob->Data == NULL) { DEBUG ((DEBUG_INFO, "%a: no kernel present -> quit\n", __func__));
Status = EFI_NOT_FOUND; Status = EFI_NOT_FOUND;
goto FreeBlobs; goto FreeBlobs;
} }
@ -1106,7 +1171,9 @@ QemuKernelLoaderFsDxeEntrypoint (
goto FreeBlobs; goto FreeBlobs;
} }
if (KernelBlob[KernelBlobTypeInitrd].Size > 0) { Blob = FindKernelBlob (L"initrd");
if (Blob != NULL) {
DEBUG ((DEBUG_INFO, "%a: initrd setup\n", __func__));
InitrdLoadFile2Handle = NULL; InitrdLoadFile2Handle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces ( Status = gBS->InstallMultipleProtocolInterfaces (
&InitrdLoadFile2Handle, &InitrdLoadFile2Handle,
@ -1141,13 +1208,11 @@ UninstallFileSystemHandle:
ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR (Status);
FreeBlobs: FreeBlobs:
while (BlobType > 0) { while (mKernelBlobs != NULL) {
CurrentBlob = &mKernelBlob[--BlobType]; Blob = mKernelBlobs;
if (CurrentBlob->Data != NULL) { mKernelBlobs = Blob->Next;
FreePool (CurrentBlob->Data); FreePool (Blob->Data);
CurrentBlob->Size = 0; FreePool (Blob);
CurrentBlob->Data = NULL;
}
} }
return Status; return Status;