From 126b21b719f88b3d91866cf103fc88b41c728dfc Mon Sep 17 00:00:00 2001
From: Mikhail Krichanov <mikhailkrichanov@gmail.com>
Date: Fri, 23 Feb 2024 12:57:09 +0300
Subject: [PATCH] Ring3: Added SysCallHandleProtocol and
 SIMPLE_FILE_SYSTEM_PROTOCOL wrapper.

---
 MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf   |   1 +
 .../Core/Dxe/DxeRing3/Ring3UefiBootServices.c |  24 +-
 MdeModulePkg/Core/Dxe/SysCall/BootServices.c  |  57 ++++-
 .../Core/Dxe/SysCall/SupportedProtocols.c     | 231 +++++++++++++++++-
 .../Core/Dxe/SysCall/SupportedProtocols.h     |  11 +-
 MdePkg/Include/Uefi/UefiSpec.h                |   1 +
 6 files changed, 319 insertions(+), 6 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf b/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf
index cfcb4d43ed..c2b0c004de 100644
--- a/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf
+++ b/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.inf
@@ -44,6 +44,7 @@
   gEfiLoadedImageProtocolGuid          ## SOMETIMES_CONSUMES
   gEfiDiskIoProtocolGuid               ## SOMETIMES_CONSUMES
   gEfiBlockIoProtocolGuid              ## SOMETIMES_CONSUMES
+  gEfiDevicePathProtocolGuid           ## SOMETIMES_CONSUMES
 
 [Depex]
   TRUE
diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c
index 22acc09f50..5e26a67fea 100644
--- a/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c
+++ b/MdeModulePkg/Core/Dxe/DxeRing3/Ring3UefiBootServices.c
@@ -208,12 +208,31 @@ Ring3UninstallProtocolInterface (
 EFI_STATUS
 EFIAPI
 Ring3HandleProtocol (
-  IN EFI_HANDLE  UserHandle,
+  IN EFI_HANDLE  CoreUserHandle,
   IN EFI_GUID    *Protocol,
   OUT VOID       **Interface
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS  Status;
+
+  Status = SysCall (
+             SysCallHandleProtocol,
+             CoreUserHandle,
+             Protocol,
+             Interface
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Ring3: Failed to get handle of protocol %g - %r\n", Protocol, Status));
+    return Status;
+  }
+
+  if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_UNSUPPORTED;
+  }
+
+  return Status;
 }
 
 EFI_STATUS
@@ -397,7 +416,6 @@ Ring3OpenProtocol (
              Attributes
              );
   if (EFI_ERROR (Status)) {
-    // DEBUG ((DEBUG_ERROR, "Ring3: Failed to open protocol %g - %r\n", Protocol, Status));
     return Status;
   }
 
diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
index b27abfcd92..c081e1c0e1 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
@@ -61,6 +61,16 @@ FindGuid (
     *Core     = &gEfiComponentNameProtocolGuid;
     *CoreSize = sizeof (EFI_COMPONENT_NAME_PROTOCOL);
 
+  } else if (CompareGuid (Ring3, &gEfiDevicePathProtocolGuid)) {
+
+    *Core     = &gEfiDevicePathProtocolGuid;
+    *CoreSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);
+
+  } else if (CompareGuid (Ring3, &gEfiSimpleFileSystemProtocolGuid)) {
+
+    *Core     = &gEfiSimpleFileSystemProtocolGuid;
+    *CoreSize = sizeof (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL);
+
   } else {
     DEBUG ((DEBUG_ERROR, "Ring0: Unknown protocol.\n"));
     return EFI_NOT_FOUND;
@@ -130,7 +140,8 @@ CallBootService (
   VOID       *CoreArgList[MAX_LIST];
   EFI_HANDLE CoreHandle;
 
-  EFI_DRIVER_BINDING_PROTOCOL *CoreDriverBinding;
+  EFI_DRIVER_BINDING_PROTOCOL      *CoreDriverBinding;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *CoreSimpleFileSystem;
   //
   // TODO: Check User variables.
   //
@@ -258,6 +269,16 @@ CallBootService (
           CoreDriverBinding->Supported = CoreDriverBindingSupported;
           CoreDriverBinding->Start     = CoreDriverBindingStart;
           CoreDriverBinding->Stop      = CoreDriverBindingStop;
+        } else if (CompareGuid ((EFI_GUID *)CoreArgList[Index], &gEfiSimpleFileSystemProtocolGuid)) {
+          CoreSimpleFileSystem = (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *)CoreArgList[Index + 1];
+
+          mRing3SimpleFileSystemProtocol.OpenVolume = CoreSimpleFileSystem->OpenVolume;
+
+          CoreSimpleFileSystem->OpenVolume = CoreOpenVolume;
+
+          DisableSMAP ();
+          mRing3SimpleFileSystemPointer = (EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *)UserArgList[Index + 1];
+          EnableSMAP ();
         }
       }
 
@@ -324,6 +345,40 @@ CallBootService (
 
       return Status;
 
+    case SysCallHandleProtocol:
+      //
+      // Argument 1: EFI_HANDLE  CoreUserHandle
+      // Argument 2: EFI_GUID    *Protocol
+      // Argument 3: VOID        **Interface
+      //
+      DisableSMAP ();
+      Status = FindGuid ((EFI_GUID *)CoreRbp->Argument2, &CoreProtocol, &MemoryCoreSize);
+      EnableSMAP ();
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+
+      Status = gBS->HandleProtocol (
+                      (EFI_HANDLE)CoreRbp->Argument1,
+                      CoreProtocol,
+                      &Interface
+                      );
+
+      DisableSMAP ();
+      if (Interface != NULL) {
+
+        Interface = AllocateRing3Copy (Interface, MemoryCoreSize, MemoryCoreSize);
+        if (Interface == NULL) {
+          EnableSMAP ();
+          return EFI_OUT_OF_RESOURCES;
+        }
+      }
+
+      *(VOID **)CoreRbp->Argument3 = Interface;
+      EnableSMAP ();
+
+      return Status;
+
     case SysCallBlockIoReset:
       //
       // Argument 1: EFI_BLOCK_IO_PROTOCOL  *This
diff --git a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
index 0d93111f01..2335423bf9 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
@@ -7,7 +7,12 @@
 
 #include "DxeMain.h"
 
-EFI_DRIVER_BINDING_PROTOCOL  mRing3DriverBindingProtocol;
+EFI_DRIVER_BINDING_PROTOCOL      mRing3DriverBindingProtocol;
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  mRing3SimpleFileSystemProtocol;
+EFI_FILE_PROTOCOL                mRing3FileProtocol;
+
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *mRing3SimpleFileSystemPointer;
+EFI_FILE_PROTOCOL                *mRing3FilePointer;
 
 EFI_STATUS
 EFIAPI
@@ -180,3 +185,227 @@ CoreDriverBindingStop (
 
   return Status;
 }
+
+EFI_STATUS
+EFIAPI
+CoreFileOpen (
+  IN EFI_FILE_PROTOCOL        *This,
+  OUT EFI_FILE_PROTOCOL       **NewHandle,
+  IN CHAR16                   *FileName,
+  IN UINT64                   OpenMode,
+  IN UINT64                   Attributes
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileClose (
+  IN EFI_FILE_PROTOCOL  *This
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileDelete (
+  IN EFI_FILE_PROTOCOL  *This
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileRead (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN OUT UINTN                *BufferSize,
+  OUT VOID                    *Buffer
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileWrite (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN OUT UINTN                *BufferSize,
+  IN VOID                     *Buffer
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileSetPosition (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN UINT64                   Position
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileGetPosition (
+  IN EFI_FILE_PROTOCOL        *This,
+  OUT UINT64                  *Position
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileGetInfo (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN EFI_GUID                 *InformationType,
+  IN OUT UINTN                *BufferSize,
+  OUT VOID                    *Buffer
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileSetInfo (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN EFI_GUID                 *InformationType,
+  IN UINTN                    BufferSize,
+  IN VOID                     *Buffer
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileFlush (
+  IN EFI_FILE_PROTOCOL  *This
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileOpenEx (
+  IN EFI_FILE_PROTOCOL        *This,
+  OUT EFI_FILE_PROTOCOL       **NewHandle,
+  IN CHAR16                   *FileName,
+  IN UINT64                   OpenMode,
+  IN UINT64                   Attributes,
+  IN OUT EFI_FILE_IO_TOKEN    *Token
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileReadEx (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN OUT EFI_FILE_IO_TOKEN    *Token
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileWriteEx (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN OUT EFI_FILE_IO_TOKEN    *Token
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreFileFlushEx (
+  IN EFI_FILE_PROTOCOL        *This,
+  IN OUT EFI_FILE_IO_TOKEN    *Token
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CoreOpenVolume (
+  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+  OUT EFI_FILE_PROTOCOL               **Root
+  )
+{
+  EFI_STATUS         Status;
+  EFI_FILE_PROTOCOL  **Ring3Root;
+
+  DisableSMAP ();
+  Status = CoreAllocatePool (EfiRing3MemoryType, sizeof (EFI_FILE_PROTOCOL *), (VOID **)&Ring3Root);
+  EnableSMAP ();
+  if (EFI_ERROR (Status)) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = GoToRing3 (
+             2,
+             (VOID *)mRing3SimpleFileSystemProtocol.OpenVolume,
+             mRing3SimpleFileSystemPointer,
+             Ring3Root
+             );
+  if (EFI_ERROR (Status)) {
+    *Root = NULL;
+    DisableSMAP ();
+    FreePool (Ring3Root);
+    EnableSMAP ();
+    return Status;
+  }
+
+  *Root = AllocatePool (sizeof (EFI_FILE_PROTOCOL));
+
+  DisableSMAP ();
+  mRing3FileProtocol.Revision    = (*Ring3Root)->Revision;
+  mRing3FileProtocol.Open        = (*Ring3Root)->Open;
+  mRing3FileProtocol.Close       = (*Ring3Root)->Close;
+  mRing3FileProtocol.Delete      = (*Ring3Root)->Delete;
+  mRing3FileProtocol.Read        = (*Ring3Root)->Read;
+  mRing3FileProtocol.Write       = (*Ring3Root)->Write;
+  mRing3FileProtocol.GetPosition = (*Ring3Root)->GetPosition;
+  mRing3FileProtocol.SetPosition = (*Ring3Root)->SetPosition;
+  mRing3FileProtocol.GetInfo     = (*Ring3Root)->GetInfo;
+  mRing3FileProtocol.SetInfo     = (*Ring3Root)->SetInfo;
+  mRing3FileProtocol.Flush       = (*Ring3Root)->Flush;
+  mRing3FileProtocol.OpenEx      = (*Ring3Root)->OpenEx;
+  mRing3FileProtocol.ReadEx      = (*Ring3Root)->ReadEx;
+  mRing3FileProtocol.WriteEx     = (*Ring3Root)->WriteEx;
+  mRing3FileProtocol.FlushEx     = (*Ring3Root)->FlushEx;
+
+  mRing3FilePointer = *Ring3Root;
+
+  FreePool (Ring3Root);
+  EnableSMAP ();
+
+  (*Root)->Revision    = mRing3FileProtocol.Revision;
+  (*Root)->Open        = CoreFileOpen;
+  (*Root)->Close       = CoreFileClose;
+  (*Root)->Delete      = CoreFileDelete;
+  (*Root)->Read        = CoreFileRead;
+  (*Root)->Write       = CoreFileWrite;
+  (*Root)->GetPosition = CoreFileGetPosition;
+  (*Root)->SetPosition = CoreFileSetPosition;
+  (*Root)->GetInfo     = CoreFileGetInfo;
+  (*Root)->SetInfo     = CoreFileSetInfo;
+  (*Root)->Flush       = CoreFileFlush;
+  (*Root)->OpenEx      = CoreFileOpenEx;
+  (*Root)->ReadEx      = CoreFileReadEx;
+  (*Root)->WriteEx     = CoreFileWriteEx;
+  (*Root)->FlushEx     = CoreFileFlushEx;
+
+  return Status;
+}
diff --git a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h
index 6862030896..200c51d242 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h
+++ b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.h
@@ -10,7 +10,9 @@
 #include <Protocol/DevicePathUtilities.h>
 #include <Protocol/DiskIo.h>
 
-extern EFI_DRIVER_BINDING_PROTOCOL  mRing3DriverBindingProtocol;
+extern EFI_DRIVER_BINDING_PROTOCOL      mRing3DriverBindingProtocol;
+extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  mRing3SimpleFileSystemProtocol;
+extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *mRing3SimpleFileSystemPointer;
 
 EFI_STATUS
 EFIAPI
@@ -36,3 +38,10 @@ CoreDriverBindingStop (
   IN  UINTN                                 NumberOfChildren,
   IN  EFI_HANDLE                            *ChildHandleBuffer OPTIONAL
   );
+
+EFI_STATUS
+EFIAPI
+CoreOpenVolume (
+  IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL        *This,
+  OUT EFI_FILE_PROTOCOL                     **Root
+  );
diff --git a/MdePkg/Include/Uefi/UefiSpec.h b/MdePkg/Include/Uefi/UefiSpec.h
index e8b5fe8c74..eabe704fa1 100644
--- a/MdePkg/Include/Uefi/UefiSpec.h
+++ b/MdePkg/Include/Uefi/UefiSpec.h
@@ -2021,6 +2021,7 @@ typedef enum {
   SysCallAllocatePool,
   SysCallFreePool,
   SysCallCloseProtocol,
+  SysCallHandleProtocol,
   //
   // Protocols
   //