]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Re-org the EBC thunk code for better code maintenance.
authorjyao1 <jyao1@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 23 Nov 2011 13:23:34 +0000 (13:23 +0000)
committerjyao1 <jyao1@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 23 Nov 2011 13:23:34 +0000 (13:23 +0000)
signed-off-by: jyao1
reviewed-by: lgao4

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12769 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/EbcDxe/Ia32/EbcSupport.c
MdeModulePkg/Universal/EbcDxe/X64/EbcSupport.c

index da1ad2cd5d8f68b324acb4c17452f3f7da72c615..41dc3a858556164f0f5d16c874d0d2a7425be9d1 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
   This module contains EBC support routines that are customized based on\r
-  the target processor.\r
+  the target ia32 processor.\r
 \r
 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
@@ -23,10 +23,47 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //       platform-specific configurations.\r
 //\r
 #define VM_STACK_SIZE   (1024 * 4)\r
-#define EBC_THUNK_SIZE  32\r
 \r
 #define STACK_REMAIN_SIZE (1024 * 4)\r
 \r
+//\r
+// This is instruction buffer used to create EBC thunk\r
+//\r
+#define EBC_ENTRYPOINT_SIGNATURE           0xAFAFAFAF\r
+#define EBC_LL_EBC_ENTRYPOINT_SIGNATURE    0xFAFAFAFA\r
+UINT8  mInstructionBufferTemplate[] = {\r
+  //\r
+  // Add a magic code here to help the VM recognize the thunk..\r
+  // mov eax, 0xca112ebc  => B8 BC 2E 11 CA\r
+  //\r
+  0xB8, 0xBC, 0x2E, 0x11, 0xCA,\r
+  //\r
+  // Add code bytes to load up a processor register with the EBC entry point.\r
+  //  mov eax, EbcEntryPoint  => B8 XX XX XX XX (To be fixed at runtime)\r
+  // These 4 bytes of the thunk entry is the address of the EBC\r
+  // entry point.\r
+  //\r
+  0xB8, \r
+    (UINT8)(EBC_ENTRYPOINT_SIGNATURE & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),\r
+  //\r
+  // Stick in a load of ecx with the address of appropriate VM function.\r
+  //  mov ecx, EbcLLEbcInterpret  => B9 XX XX XX XX (To be fixed at runtime)\r
+  //\r
+  0xB9,\r
+    (UINT8)(EBC_LL_EBC_ENTRYPOINT_SIGNATURE & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),\r
+  //\r
+  // Stick in jump opcode bytes\r
+  //  jmp ecx => FF E1\r
+  //\r
+  0xFF, 0xE1,\r
+};\r
+\r
 /**\r
   Begin executing an EBC image.\r
   This is used for Ebc Thunk call.\r
@@ -79,54 +116,37 @@ EbcLLCALLEX (
 {\r
   UINTN    IsThunk;\r
   UINTN    TargetEbcAddr;\r
+  UINT8    InstructionBuffer[sizeof(mInstructionBufferTemplate)];\r
+  UINTN    Index;\r
+  UINTN    IndexOfEbcEntrypoint;\r
 \r
   IsThunk       = 1;\r
   TargetEbcAddr = 0;\r
+  IndexOfEbcEntrypoint = 0;\r
 \r
   //\r
   // Processor specific code to check whether the callee is a thunk to EBC.\r
   //\r
-  if (*((UINT8 *)FuncAddr) != 0xB8) {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 1) != 0xBC)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 2) != 0x2E)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 3) != 0x11)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 4) != 0xCA)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 5) != 0xB8)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 10) != 0xB9)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 15) != 0xFF)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
+  CopyMem (InstructionBuffer, (VOID *)FuncAddr, sizeof(InstructionBuffer));\r
+  //\r
+  // Fill the signature according to mInstructionBufferTemplate\r
+  //\r
+  for (Index = 0; Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {\r
+    if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_ENTRYPOINT_SIGNATURE) {\r
+      *(UINTN *)&InstructionBuffer[Index] = EBC_ENTRYPOINT_SIGNATURE;\r
+      IndexOfEbcEntrypoint = Index;\r
+    }\r
+    if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {\r
+      *(UINTN *)&InstructionBuffer[Index] = EBC_LL_EBC_ENTRYPOINT_SIGNATURE;\r
+    }\r
   }\r
-  if (*((UINT8 *)FuncAddr + 16) != 0xE1)  {\r
+  //\r
+  // Check if we need thunk to native\r
+  //\r
+  if (CompareMem (InstructionBuffer, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate)) != 0) {\r
     IsThunk = 0;\r
-    goto Action;\r
   }\r
 \r
-  TargetEbcAddr = ((UINTN)(*((UINT8 *)FuncAddr + 9)) << 24) + ((UINTN)(*((UINT8 *)FuncAddr + 8)) << 16) +\r
-                    ((UINTN)(*((UINT8 *)FuncAddr + 7)) << 8) + ((UINTN)(*((UINT8 *)FuncAddr + 6)));\r
-\r
-Action:\r
   if (IsThunk == 1){\r
     //\r
     // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and\r
@@ -139,11 +159,12 @@ Action:
     VmPtr->Gpr[0] -= 8;\r
     VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (UINTN) (VmPtr->Ip + Size));\r
 \r
+    CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr + IndexOfEbcEntrypoint, sizeof(UINTN));\r
     VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr;\r
   } else {\r
     //\r
     // The callee is not a thunk to EBC, call native code,\r
-    // and get return value\r
+    // and get return value.\r
     //\r
     VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr);\r
 \r
@@ -449,8 +470,6 @@ EbcCreateThunks (
   UINT8       *Ptr;\r
   UINT8       *ThunkBase;\r
   UINT32      Index;\r
-  UINT32      Addr;\r
-  INT32       Size;\r
   INT32       ThunkSize;\r
 \r
   //\r
@@ -460,10 +479,9 @@ EbcCreateThunks (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Size      = EBC_THUNK_SIZE;\r
-  ThunkSize = Size;\r
+  ThunkSize = sizeof(mInstructionBufferTemplate);\r
 \r
-  Ptr = AllocatePool (Size);\r
+  Ptr = AllocatePool (sizeof(mInstructionBufferTemplate));\r
 \r
   if (Ptr == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -481,74 +499,26 @@ EbcCreateThunks (
   *Thunk = (VOID *) Ptr;\r
 \r
   //\r
-  // Add a magic code here to help the VM recognize the thunk..\r
-  // mov eax, 0xca112ebc  => B8 BC 2E 11 CA\r
+  // Copy whole thunk instruction buffer template\r
   //\r
-  *Ptr = 0xB8;\r
-  Ptr++;\r
-  Size--;\r
-  Addr = (UINT32) 0xCA112EBC;\r
-  for (Index = 0; Index < sizeof (Addr); Index++) {\r
-    *Ptr = (UINT8) (UINTN) Addr;\r
-    Addr >>= 8;\r
-    Ptr++;\r
-    Size--;\r
-  }\r
+  CopyMem (Ptr, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate));\r
 \r
   //\r
-  // Add code bytes to load up a processor register with the EBC entry point.\r
-  // mov eax, 0xaa55aa55  => B8 55 AA 55 AA\r
-  // The first 8 bytes of the thunk entry is the address of the EBC\r
-  // entry point.\r
+  // Patch EbcEntryPoint and EbcLLEbcInterpret\r
   //\r
-  *Ptr = 0xB8;\r
-  Ptr++;\r
-  Size--;\r
-  Addr = (UINT32) EbcEntryPoint;\r
-  for (Index = 0; Index < sizeof (Addr); Index++) {\r
-    *Ptr = (UINT8) (UINTN) Addr;\r
-    Addr >>= 8;\r
-    Ptr++;\r
-    Size--;\r
-  }\r
-  //\r
-  // Stick in a load of ecx with the address of appropriate VM function.\r
-  //  mov ecx 12345678h  => 0xB9 0x78 0x56 0x34 0x12\r
-  //\r
-  if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {\r
-    Addr = (UINT32) (UINTN) EbcLLExecuteEbcImageEntryPoint;\r
-  } else {\r
-    Addr = (UINT32) (UINTN) EbcLLEbcInterpret;\r
+  for (Index = 0; Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {\r
+    if (*(UINTN *)&Ptr[Index] == EBC_ENTRYPOINT_SIGNATURE) {\r
+      *(UINTN *)&Ptr[Index] = (UINTN)EbcEntryPoint;\r
+    }\r
+    if (*(UINTN *)&Ptr[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {\r
+      if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {\r
+        *(UINTN *)&Ptr[Index] = (UINTN)EbcLLExecuteEbcImageEntryPoint;\r
+      } else {\r
+        *(UINTN *)&Ptr[Index] = (UINTN)EbcLLEbcInterpret;\r
+      }\r
+    }\r
   }\r
 \r
-  //\r
-  // MOV ecx\r
-  //\r
-  *Ptr = 0xB9;\r
-  Ptr++;\r
-  Size--;\r
-  for (Index = 0; Index < sizeof (Addr); Index++) {\r
-    *Ptr = (UINT8) Addr;\r
-    Addr >>= 8;\r
-    Ptr++;\r
-    Size--;\r
-  }\r
-  //\r
-  // Stick in jump opcode bytes for jmp ecx => 0xFF 0xE1\r
-  //\r
-  *Ptr = 0xFF;\r
-  Ptr++;\r
-  Size--;\r
-  *Ptr = 0xE1;\r
-  Size--;\r
-\r
-  //\r
-  // Double check that our defined size is ok (application error)\r
-  //\r
-  if (Size < 0) {\r
-    ASSERT (FALSE);\r
-    return EFI_BUFFER_TOO_SMALL;\r
-  }\r
   //\r
   // Add the thunk to the list for this image. Do this last since the add\r
   // function flushes the cache for us.\r
index a31422b62acdb39182cbfec25fe7600f0d1f9449..3f99a1a6e296776bd18999c3697d97960a9539c3 100644 (file)
@@ -23,10 +23,55 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //       platform-specific configurations.\r
 //\r
 #define VM_STACK_SIZE   (1024 * 8)\r
-#define EBC_THUNK_SIZE  64\r
 \r
 #define STACK_REMAIN_SIZE (1024 * 4)\r
 \r
+//\r
+// This is instruction buffer used to create EBC thunk\r
+//\r
+#define EBC_ENTRYPOINT_SIGNATURE           0xAFAFAFAFAFAFAFAFull\r
+#define EBC_LL_EBC_ENTRYPOINT_SIGNATURE    0xFAFAFAFAFAFAFAFAull\r
+UINT8  mInstructionBufferTemplate[] = {\r
+  //\r
+  // Add a magic code here to help the VM recognize the thunk..\r
+  // mov rax, 0xca112ebcca112ebc  => 48 B8 BC 2E 11 CA BC 2E 11 CA\r
+  //\r
+  0x48, 0xB8, 0xBC, 0x2E, 0x11, 0xCA, 0xBC, 0x2E, 0x11, 0xCA,\r
+  //\r
+  // Add code bytes to load up a processor register with the EBC entry point.\r
+  //  mov r10, EbcEntryPoint  => 49 BA XX XX XX XX XX XX XX XX (To be fixed at runtime)\r
+  // These 8 bytes of the thunk entry is the address of the EBC\r
+  // entry point.\r
+  //\r
+  0x49, 0xBA, \r
+    (UINT8)(EBC_ENTRYPOINT_SIGNATURE & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),\r
+    (UINT8)((EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),\r
+  //\r
+  // Stick in a load of r11 with the address of appropriate VM function.\r
+  //  mov r11, EbcLLEbcInterpret  => 49 BB XX XX XX XX XX XX XX XX (To be fixed at runtime)\r
+  //\r
+  0x49, 0xBB,\r
+    (UINT8)(EBC_LL_EBC_ENTRYPOINT_SIGNATURE & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 8) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 16) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 24) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 32) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 40) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 48) & 0xFF),\r
+    (UINT8)((EBC_LL_EBC_ENTRYPOINT_SIGNATURE >> 56) & 0xFF),\r
+  //\r
+  // Stick in jump opcode bytes\r
+  //  jmp r11 => 41 FF E3\r
+  //\r
+  0x41, 0xFF, 0xE3,\r
+};\r
+\r
 /**\r
   Begin executing an EBC image.\r
   This is used for Ebc Thunk call.\r
@@ -382,8 +427,6 @@ EbcCreateThunks (
   UINT8       *Ptr;\r
   UINT8       *ThunkBase;\r
   UINT32      Index;\r
-  UINT64      Addr;\r
-  INT32       Size;\r
   INT32       ThunkSize;\r
 \r
   //\r
@@ -393,10 +436,9 @@ EbcCreateThunks (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Size      = EBC_THUNK_SIZE;\r
-  ThunkSize = Size;\r
+  ThunkSize = sizeof(mInstructionBufferTemplate);\r
 \r
-  Ptr = AllocatePool (Size);\r
+  Ptr = AllocatePool (sizeof(mInstructionBufferTemplate));\r
 \r
   if (Ptr == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -414,89 +456,26 @@ EbcCreateThunks (
   *Thunk = (VOID *) Ptr;\r
 \r
   //\r
-  // Add a magic code here to help the VM recognize the thunk..\r
-  // mov rax, ca112ebccall2ebch  => 48 B8 BC 2E 11 CA BC 2E 11 CA\r
-  //\r
-  *Ptr = 0x48;\r
-  Ptr++;\r
-  Size--;\r
-  *Ptr = 0xB8;\r
-  Ptr++;\r
-  Size--;\r
-  Addr = (UINT64) 0xCA112EBCCA112EBCULL;\r
-  for (Index = 0; Index < sizeof (Addr); Index++) {\r
-    *Ptr = (UINT8) (UINTN) Addr;\r
-    Addr >>= 8;\r
-    Ptr++;\r
-    Size--;\r
-  }\r
-\r
+  // Copy whole thunk instruction buffer template\r
   //\r
-  // Add code bytes to load up a processor register with the EBC entry point.\r
-  // mov r10, 123456789abcdef0h  => 49 BA F0 DE BC 9A 78 56 34 12\r
-  // The first 8 bytes of the thunk entry is the address of the EBC\r
-  // entry point.\r
-  //\r
-  *Ptr = 0x49;\r
-  Ptr++;\r
-  Size--;\r
-  *Ptr = 0xBA;\r
-  Ptr++;\r
-  Size--;\r
-  Addr = (UINT64) EbcEntryPoint;\r
-  for (Index = 0; Index < sizeof (Addr); Index++) {\r
-    *Ptr = (UINT8) (UINTN) Addr;\r
-    Addr >>= 8;\r
-    Ptr++;\r
-    Size--;\r
-  }\r
+  CopyMem (Ptr, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate));\r
 \r
   //\r
-  // Stick in a load of ecx with the address of appropriate VM function.\r
-  // Using r11 because it's a volatile register and won't be used in this\r
-  // point.\r
-  // mov r11 123456789abcdef0h  => 49 BB F0 DE BC 9A 78 56 34 12\r
+  // Patch EbcEntryPoint and EbcLLEbcInterpret\r
   //\r
-  if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {\r
-    Addr = (UINTN) EbcLLExecuteEbcImageEntryPoint;\r
-  } else {\r
-    Addr = (UINTN) EbcLLEbcInterpret;\r
+  for (Index = 0; Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {\r
+    if (*(UINTN *)&Ptr[Index] == EBC_ENTRYPOINT_SIGNATURE) {\r
+      *(UINTN *)&Ptr[Index] = (UINTN)EbcEntryPoint;\r
+    }\r
+    if (*(UINTN *)&Ptr[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {\r
+      if ((Flags & FLAG_THUNK_ENTRY_POINT) != 0) {\r
+        *(UINTN *)&Ptr[Index] = (UINTN)EbcLLExecuteEbcImageEntryPoint;\r
+      } else {\r
+        *(UINTN *)&Ptr[Index] = (UINTN)EbcLLEbcInterpret;\r
+      }\r
+    }\r
   }\r
 \r
-  //\r
-  // mov r11 Addr => 0x49 0xBB\r
-  //\r
-  *Ptr = 0x49;\r
-  Ptr++;\r
-  Size--;\r
-  *Ptr = 0xBB;\r
-  Ptr++;\r
-  Size--;\r
-  for (Index = 0; Index < sizeof (Addr); Index++) {\r
-    *Ptr = (UINT8) Addr;\r
-    Addr >>= 8;\r
-    Ptr++;\r
-    Size--;\r
-  }\r
-  //\r
-  // Stick in jump opcode bytes for jmp r11 => 0x41 0xFF 0xE3\r
-  //\r
-  *Ptr = 0x41;\r
-  Ptr++;\r
-  Size--;\r
-  *Ptr = 0xFF;\r
-  Ptr++;\r
-  Size--;\r
-  *Ptr = 0xE3;\r
-  Size--;\r
-\r
-  //\r
-  // Double check that our defined size is ok (application error)\r
-  //\r
-  if (Size < 0) {\r
-    ASSERT (FALSE);\r
-    return EFI_BUFFER_TOO_SMALL;\r
-  }\r
   //\r
   // Add the thunk to the list for this image. Do this last since the add\r
   // function flushes the cache for us.\r
@@ -533,65 +512,37 @@ EbcLLCALLEX (
 {\r
   UINTN    IsThunk;\r
   UINTN    TargetEbcAddr;\r
+  UINT8    InstructionBuffer[sizeof(mInstructionBufferTemplate)];\r
+  UINTN    Index;\r
+  UINTN    IndexOfEbcEntrypoint;\r
 \r
   IsThunk       = 1;\r
   TargetEbcAddr = 0;\r
+  IndexOfEbcEntrypoint = 0;\r
 \r
   //\r
   // Processor specific code to check whether the callee is a thunk to EBC.\r
   //\r
-  if (*((UINT8 *)FuncAddr) != 0x48) {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 1) != 0xB8) {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 2) != 0xBC)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 3) != 0x2E)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 4) != 0x11)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 5) != 0xCA)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 6) != 0xBC)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 7) != 0x2E)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 8) != 0x11)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 9) != 0xCA)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
-  }\r
-  if (*((UINT8 *)FuncAddr + 10) != 0x49)  {\r
-    IsThunk = 0;\r
-    goto Action;\r
+  CopyMem (InstructionBuffer, (VOID *)FuncAddr, sizeof(InstructionBuffer));\r
+  //\r
+  // Fill the signature according to mInstructionBufferTemplate\r
+  //\r
+  for (Index = 0; Index < sizeof(mInstructionBufferTemplate) - sizeof(UINTN); Index++) {\r
+    if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_ENTRYPOINT_SIGNATURE) {\r
+      *(UINTN *)&InstructionBuffer[Index] = EBC_ENTRYPOINT_SIGNATURE;\r
+      IndexOfEbcEntrypoint = Index;\r
+    }\r
+    if (*(UINTN *)&mInstructionBufferTemplate[Index] == EBC_LL_EBC_ENTRYPOINT_SIGNATURE) {\r
+      *(UINTN *)&InstructionBuffer[Index] = EBC_LL_EBC_ENTRYPOINT_SIGNATURE;\r
+    }\r
   }\r
-  if (*((UINT8 *)FuncAddr + 11) != 0xBA)  {\r
+  //\r
+  // Check if we need thunk to native\r
+  //\r
+  if (CompareMem (InstructionBuffer, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate)) != 0) {\r
     IsThunk = 0;\r
-    goto Action;\r
   }\r
 \r
-  CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr + 12, 8);\r
-\r
-Action:\r
   if (IsThunk == 1){\r
     //\r
     // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and\r
@@ -602,8 +553,9 @@ Action:
     VmWriteMemN (VmPtr, (UINTN) VmPtr->Gpr[0], (UINTN) FramePtr);\r
     VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->Gpr[0];\r
     VmPtr->Gpr[0] -= 8;\r
-    VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (VmPtr->Ip + Size));\r
+    VmWriteMem64 (VmPtr, (UINTN) VmPtr->Gpr[0], (UINT64) (UINTN) (VmPtr->Ip + Size));\r
 \r
+    CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr + IndexOfEbcEntrypoint, sizeof(UINTN));\r
     VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr;\r
   } else {\r
     //\r