From ab600336fb413297ab833a2c1200f1ba8e09e23d Mon Sep 17 00:00:00 2001
From: Mikhail Krichanov <mikhailkrichanov@gmail.com>
Date: Wed, 10 Jul 2024 13:29:20 +0300
Subject: [PATCH] Ring3: Fixed arguments alignment bug for ARM.

---
 MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.c     | 18 ++++++++
 MdeModulePkg/Core/Dxe/SysCall/BootServices.c  | 46 +++++++++++++++++++
 .../Core/Dxe/SysCall/SupportedProtocols.c     | 31 ++++++++++++-
 3 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.c b/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.c
index da40513a94..492b2cd372 100644
--- a/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.c
+++ b/MdeModulePkg/Core/Dxe/DxeRing3/DxeRing3.c
@@ -166,6 +166,19 @@ EFI_STATUS
   IN UINTN Argument7
   );
 
+typedef
+EFI_STATUS
+(EFIAPI *FUNCTION_8)(
+  IN UINTN Argument1,
+  IN UINTN Argument2,
+  IN UINTN Argument3,
+  IN UINTN Argument4,
+  IN UINTN Argument5,
+  IN UINTN Argument6,
+  IN UINTN Argument7,
+  IN UINTN Argument8
+  );
+
 VOID
 EFIAPI
 Ring3Call (
@@ -181,6 +194,7 @@ Ring3Call (
   FUNCTION_5  Function5;
   FUNCTION_6  Function6;
   FUNCTION_7  Function7;
+  FUNCTION_8  Function8;
 
   switch (Data->NumberOfArguments) {
     case 0:
@@ -215,6 +229,10 @@ Ring3Call (
       Function7 = (FUNCTION_7)Data->EntryPoint;
       Status = Function7 (Data->Arguments[0], Data->Arguments[1], Data->Arguments[2], Data->Arguments[3], Data->Arguments[4], Data->Arguments[5], Data->Arguments[6]);
       break;
+    case 8:
+      Function8 = (FUNCTION_8)Data->EntryPoint;
+      Status = Function8 (Data->Arguments[0], Data->Arguments[1], Data->Arguments[2], Data->Arguments[3], Data->Arguments[4], Data->Arguments[5], Data->Arguments[6], Data->Arguments[7]);
+      break;
     default:
       Status = EFI_UNSUPPORTED;
       break;
diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
index eb9c9b0924..9b6b82f5c7 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
@@ -315,6 +315,8 @@ CallBootService (
   gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)UserRsp, &Attributes);
   ASSERT ((Attributes & EFI_MEMORY_USER) != 0);
 
+  DEBUG ((DEBUG_VERBOSE, "Type: %a\n", SysCallNames[Type]));
+
   switch (Type) {
     case SysCallLocateProtocol:
       //
@@ -854,11 +856,22 @@ CallBootService (
         return EFI_NOT_FOUND;
       }
 
+#if defined (MDE_CPU_ARM)
+      gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 8 * sizeof (UINTN) - 1), &Attributes);
+#else
       gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 7 * sizeof (UINTN) - 1), &Attributes);
+#endif
       ASSERT ((Attributes & EFI_MEMORY_USER) != 0);
 
       DisableSMAP ();
+#if defined (MDE_CPU_ARM)
+      //
+      // EFI_LBA Lba is aligned on 8 bytes.
+      //
+      Attributes = *(UINT64 *)&UserRsp->Arguments[6];
+#else
       Attributes = *(UINT64 *)&UserRsp->Arguments[5];
+#endif
       EnableSMAP ();
 
       Argument5 = (UINTN)AllocatePool (CoreRbp->Argument3);
@@ -900,7 +913,11 @@ CallBootService (
         return EFI_NOT_FOUND;
       }
 
+#if defined (MDE_CPU_ARM)
+      gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 8 * sizeof (UINTN) - 1), &Attributes);
+#else
       gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 7 * sizeof (UINTN) - 1), &Attributes);
+#endif
       ASSERT ((Attributes & EFI_MEMORY_USER) != 0);
 
       Argument5 = (UINTN)AllocatePool (CoreRbp->Argument3);
@@ -916,7 +933,14 @@ CallBootService (
 
       CopyMem ((VOID *)Argument5,(VOID *)UserRsp->Arguments[4], CoreRbp->Argument3);
 
+#if defined (MDE_CPU_ARM)
+      //
+      // EFI_LBA Lba is aligned on 8 bytes.
+      //
+      Attributes = *(UINT64 *)&UserRsp->Arguments[6];
+#else
       Attributes = *(UINT64 *)&UserRsp->Arguments[5];
+#endif
       EnableSMAP ();
 
       Status = BlockIo->WriteBlocks (
@@ -957,11 +981,22 @@ CallBootService (
         return EFI_NOT_FOUND;
       }
 
+#if defined (MDE_CPU_ARM)
+      gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 8 * sizeof (UINTN) - 1), &Attributes);
+#else
       gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 7 * sizeof (UINTN) - 1), &Attributes);
+#endif
       ASSERT ((Attributes & EFI_MEMORY_USER) != 0);
 
       DisableSMAP ();
+#if defined (MDE_CPU_ARM)
+      //
+      // UINT64 Offset is aligned on 8 bytes.
+      //
+      Attributes = *(UINT64 *)&UserRsp->Arguments[6];
+#else
       Attributes = *(UINT64 *)&UserRsp->Arguments[5];
+#endif
       EnableSMAP ();
 
       Argument5 = (UINTN)AllocatePool (CoreRbp->Argument3);
@@ -1003,7 +1038,11 @@ CallBootService (
         return EFI_NOT_FOUND;
       }
 
+#if defined (MDE_CPU_ARM)
+      gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 8 * sizeof (UINTN) - 1), &Attributes);
+#else
       gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)((UINTN)UserRsp + 7 * sizeof (UINTN) - 1), &Attributes);
+#endif
       ASSERT ((Attributes & EFI_MEMORY_USER) != 0);
 
       Argument5 = (UINTN)AllocatePool (CoreRbp->Argument3);
@@ -1019,7 +1058,14 @@ CallBootService (
 
       CopyMem ((VOID *)Argument5, (VOID *)UserRsp->Arguments[4], CoreRbp->Argument3);
 
+#if defined (MDE_CPU_ARM)
+      //
+      // UINT64 Offset is aligned on 8 bytes.
+      //
+      Attributes = *(UINT64 *)&UserRsp->Arguments[6];
+#else
       Attributes = *(UINT64 *)&UserRsp->Arguments[5];
+#endif
       EnableSMAP ();
 
       Status = DiskIo->WriteDisk (
diff --git a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
index 43e7e93920..349b29b9bc 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
@@ -360,7 +360,7 @@ CoreFileSetPosition (
            File->Ring3File,
            Position
            );
-#elif defined (MDE_CPU_IA32) || defined (MDE_CPU_ARM)
+#elif defined (MDE_CPU_IA32)
   //
   // UINT64 Position is passed as 2 double words on stack.
   //
@@ -370,6 +370,17 @@ CoreFileSetPosition (
            File->Ring3File,
            Position
            );
+#elif defined (MDE_CPU_ARM)
+  //
+  // UINT64 Position is passed as 2 words in 2 registers and is aligned on 8 bytes.
+  // R0 == File->Ring3File, R1 == NULL, R2 == Position_Low, R3 == Position_High.
+  //
+  return GoToRing3 (
+           4,
+           (VOID *)mRing3FileProtocol.SetPosition,
+           File->Ring3File,
+           Position
+           );
 #endif
 
 }
@@ -636,7 +647,7 @@ CoreFileOpen (
              OpenMode,
              Attributes
              );
-#elif defined (MDE_CPU_IA32) || defined (MDE_CPU_ARM)
+#elif defined (MDE_CPU_IA32)
   //
   // UINT64 OpenMode and Attributes are each passed as 2 double words on stack.
   //
@@ -649,6 +660,22 @@ CoreFileOpen (
              OpenMode,
              Attributes
              );
+#elif defined (MDE_CPU_ARM)
+  //
+  // UINT64 OpenMode and Attributes are each passed as 2 words on stack.
+  // Each of them is aligned on 8 bytes.
+  // R0 == File->Ring3File, R1 == Ring3NewHandle, R2 == Ring3FileName, R3 == NULL,
+  // [SP] == OpenMode, [SP + 8] == Attributes.
+  //
+  Status = GoToRing3 (
+             8,
+             (VOID *)mRing3FileProtocol.Open,
+             File->Ring3File,
+             Ring3NewHandle,
+             Ring3FileName,
+             OpenMode,
+             Attributes
+             );
 #endif
   if (EFI_ERROR (Status)) {
     *NewHandle = NULL;