]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.c
NetworkPkg/Ip6Dxe: Validate source data record length
[mirror_edk2.git] / OvmfPkg / QemuKernelLoaderFsDxe / QemuKernelLoaderFsDxe.c
index 8ccb1983170c11c7ecca8511f32f53242c5ac611..b09ff6a3590db34d9aaa5fd3539c4cebb5db6c76 100644 (file)
 #include <Guid/FileInfo.h>\r
 #include <Guid/FileSystemInfo.h>\r
 #include <Guid/FileSystemVolumeLabelInfo.h>\r
+#include <Guid/LinuxEfiInitrdMedia.h>\r
 #include <Guid/QemuKernelLoaderFsMedia.h>\r
 #include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
+#include <Library/DevicePathLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/QemuFwCfgLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Protocol/DevicePath.h>\r
+#include <Protocol/LoadFile2.h>\r
 #include <Protocol/SimpleFileSystem.h>\r
 \r
 //\r
@@ -84,6 +87,19 @@ STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mFileSystemDevicePath = {
   }\r
 };\r
 \r
+STATIC CONST SINGLE_VENMEDIA_NODE_DEVPATH mInitrdDevicePath = {\r
+  {\r
+    {\r
+      MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP,\r
+      { sizeof (VENDOR_DEVICE_PATH) }\r
+    },\r
+    LINUX_EFI_INITRD_MEDIA_GUID\r
+  }, {\r
+    END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    { sizeof (EFI_DEVICE_PATH_PROTOCOL) }\r
+  }\r
+};\r
+\r
 //\r
 // The "file in the EFI stub filesystem" abstraction.\r
 //\r
@@ -107,13 +123,6 @@ typedef struct {
 #define STUB_FILE_FROM_FILE(FilePointer) \\r
         CR (FilePointer, STUB_FILE, File, STUB_FILE_SIG)\r
 \r
-//\r
-// Tentative definition of the file protocol template. The initializer\r
-// (external definition) will be provided later.\r
-//\r
-STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate;\r
-\r
-\r
 //\r
 // Protocol member functions for File.\r
 //\r
@@ -121,6 +130,8 @@ STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate;
 /**\r
   Opens a new file relative to the source file's location.\r
 \r
+  (Forward declaration.)\r
+\r
   @param[in]  This        A pointer to the EFI_FILE_PROTOCOL instance that is\r
                           the file handle to the source location. This would\r
                           typically be an open handle to a directory.\r
@@ -165,65 +176,7 @@ StubFileOpen (
   IN CHAR16             *FileName,\r
   IN UINT64             OpenMode,\r
   IN UINT64             Attributes\r
-  )\r
-{\r
-  CONST STUB_FILE *StubFile;\r
-  UINTN           BlobType;\r
-  STUB_FILE       *NewStubFile;\r
-\r
-  //\r
-  // We're read-only.\r
-  //\r
-  switch (OpenMode) {\r
-    case EFI_FILE_MODE_READ:\r
-      break;\r
-\r
-    case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
-    case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:\r
-      return EFI_WRITE_PROTECTED;\r
-\r
-    default:\r
-      return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  //\r
-  // Only the root directory supports opening files in it.\r
-  //\r
-  StubFile = STUB_FILE_FROM_FILE (This);\r
-  if (StubFile->BlobType != KernelBlobTypeMax) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  //\r
-  // Locate the file.\r
-  //\r
-  for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
-    if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {\r
-      break;\r
-    }\r
-  }\r
-  if (BlobType == KernelBlobTypeMax) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Found it.\r
-  //\r
-  NewStubFile = AllocatePool (sizeof *NewStubFile);\r
-  if (NewStubFile == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  NewStubFile->Signature = STUB_FILE_SIG;\r
-  NewStubFile->BlobType  = (KERNEL_BLOB_TYPE)BlobType;\r
-  NewStubFile->Position  = 0;\r
-  CopyMem (&NewStubFile->File, &mEfiFileProtocolTemplate,\r
-    sizeof mEfiFileProtocolTemplate);\r
-  *NewHandle = &NewStubFile->File;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
+  );\r
 \r
 /**\r
   Closes a specified file handle.\r
@@ -781,6 +734,74 @@ STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {
   NULL                        // FlushEx, revision 2\r
 };\r
 \r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+StubFileOpen (\r
+  IN EFI_FILE_PROTOCOL  *This,\r
+  OUT EFI_FILE_PROTOCOL **NewHandle,\r
+  IN CHAR16             *FileName,\r
+  IN UINT64             OpenMode,\r
+  IN UINT64             Attributes\r
+  )\r
+{\r
+  CONST STUB_FILE *StubFile;\r
+  UINTN           BlobType;\r
+  STUB_FILE       *NewStubFile;\r
+\r
+  //\r
+  // We're read-only.\r
+  //\r
+  switch (OpenMode) {\r
+    case EFI_FILE_MODE_READ:\r
+      break;\r
+\r
+    case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
+    case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:\r
+      return EFI_WRITE_PROTECTED;\r
+\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Only the root directory supports opening files in it.\r
+  //\r
+  StubFile = STUB_FILE_FROM_FILE (This);\r
+  if (StubFile->BlobType != KernelBlobTypeMax) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Locate the file.\r
+  //\r
+  for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
+    if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {\r
+      break;\r
+    }\r
+  }\r
+  if (BlobType == KernelBlobTypeMax) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Found it.\r
+  //\r
+  NewStubFile = AllocatePool (sizeof *NewStubFile);\r
+  if (NewStubFile == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NewStubFile->Signature = STUB_FILE_SIG;\r
+  NewStubFile->BlobType  = (KERNEL_BLOB_TYPE)BlobType;\r
+  NewStubFile->Position  = 0;\r
+  CopyMem (&NewStubFile->File, &mEfiFileProtocolTemplate,\r
+    sizeof mEfiFileProtocolTemplate);\r
+  *NewHandle = &NewStubFile->File;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 //\r
 // Protocol member functions for SimpleFileSystem.\r
@@ -839,6 +860,48 @@ STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = {
   StubFileSystemOpenVolume\r
 };\r
 \r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+InitrdLoadFile2 (\r
+  IN      EFI_LOAD_FILE2_PROTOCOL       *This,\r
+  IN      EFI_DEVICE_PATH_PROTOCOL      *FilePath,\r
+  IN      BOOLEAN                       BootPolicy,\r
+  IN  OUT UINTN                         *BufferSize,\r
+  OUT     VOID                          *Buffer     OPTIONAL\r
+  )\r
+{\r
+  CONST KERNEL_BLOB   *InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd];\r
+\r
+  ASSERT (InitrdBlob->Size > 0);\r
+\r
+  if (BootPolicy) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (BufferSize == NULL || !IsDevicePathValid (FilePath, 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (FilePath->Type != END_DEVICE_PATH_TYPE ||\r
+      FilePath->SubType != END_ENTIRE_DEVICE_PATH_SUBTYPE) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  if (Buffer == NULL || *BufferSize < InitrdBlob->Size) {\r
+    *BufferSize = InitrdBlob->Size;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  CopyMem (Buffer, InitrdBlob->Data, InitrdBlob->Size);\r
+\r
+  *BufferSize = InitrdBlob->Size;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC CONST EFI_LOAD_FILE2_PROTOCOL     mInitrdLoadFile2 = {\r
+  InitrdLoadFile2,\r
+};\r
 \r
 //\r
 // Utility functions.\r
@@ -949,6 +1012,7 @@ QemuKernelLoaderFsDxeEntrypoint (
   KERNEL_BLOB               *KernelBlob;\r
   EFI_STATUS                Status;\r
   EFI_HANDLE                FileSystemHandle;\r
+  EFI_HANDLE                InitrdLoadFile2Handle;\r
 \r
   if (!QemuFwCfgIsAvailable ()) {\r
     return EFI_NOT_FOUND;\r
@@ -993,8 +1057,28 @@ QemuKernelLoaderFsDxeEntrypoint (
     goto FreeBlobs;\r
   }\r
 \r
+  if (KernelBlob[KernelBlobTypeInitrd].Size > 0) {\r
+    InitrdLoadFile2Handle = NULL;\r
+    Status = gBS->InstallMultipleProtocolInterfaces (&InitrdLoadFile2Handle,\r
+                    &gEfiDevicePathProtocolGuid,  &mInitrdDevicePath,\r
+                    &gEfiLoadFile2ProtocolGuid,   &mInitrdLoadFile2,\r
+                    NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "%a: InstallMultipleProtocolInterfaces(): %r\n",\r
+        __FUNCTION__, Status));\r
+      goto UninstallFileSystemHandle;\r
+    }\r
+  }\r
+\r
   return EFI_SUCCESS;\r
 \r
+UninstallFileSystemHandle:\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (FileSystemHandle,\r
+                  &gEfiDevicePathProtocolGuid,       &mFileSystemDevicePath,\r
+                  &gEfiSimpleFileSystemProtocolGuid, &mFileSystem,\r
+                  NULL);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
 FreeBlobs:\r
   while (BlobType > 0) {\r
     CurrentBlob = &mKernelBlob[--BlobType];\r