-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- EbcSupport.c\r
-\r
-Abstract:\r
-\r
+/** @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 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
---*/\r
+**/\r
\r
#include "EbcInt.h"\r
#include "EbcExecute.h"\r
+#include "EbcDebuggerHook.h"\r
\r
//\r
// NOTE: This is the stack size allocated for the interpreter\r
// 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
-VOID\r
-EbcLLCALLEX (\r
- IN VM_CONTEXT *VmPtr,\r
- IN UINTN FuncAddr,\r
- IN UINTN NewStackPointer,\r
- IN VOID *FramePtr,\r
- IN UINT8 Size\r
- )\r
-/*++\r
\r
-Routine Description:\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
- This function is called to execute an EBC CALLEX instruction. \r
+/**\r
+ Begin executing an EBC image.\r
+ This is used for Ebc Thunk call.\r
+\r
+ @return The value returned by the EBC application we're going to run.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+EbcLLEbcInterpret (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Begin executing an EBC image.\r
+ This is used for Ebc image entrypoint.\r
+\r
+ @return The value returned by the EBC application we're going to run.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+EbcLLExecuteEbcImageEntryPoint (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function is called to execute an EBC CALLEX instruction.\r
The function check the callee's content to see whether it is common native\r
code or a thunk to another piece of EBC code.\r
If the callee is common native code, use EbcLLCAllEXASM to manipulate,\r
otherwise, set the VM->IP to target EBC code directly to avoid another VM\r
be startup which cost time and stack space.\r
- \r
-Arguments:\r
-\r
- VmPtr - Pointer to a VM context.\r
- FuncAddr - Callee's address\r
- NewStackPointer - New stack pointer after the call\r
- FramePtr - New frame pointer after the call\r
- Size - The size of call instruction\r
\r
-Returns:\r
+ @param VmPtr Pointer to a VM context.\r
+ @param FuncAddr Callee's address\r
+ @param NewStackPointer New stack pointer after the call\r
+ @param FramePtr New frame pointer after the call\r
+ @param Size The size of call instruction\r
\r
- None.\r
- \r
---*/\r
+**/\r
+VOID\r
+EbcLLCALLEX (\r
+ IN VM_CONTEXT *VmPtr,\r
+ IN UINTN FuncAddr,\r
+ IN UINTN NewStackPointer,\r
+ IN VOID *FramePtr,\r
+ IN UINT8 Size\r
+ )\r
{\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
// put our return address and frame pointer on the VM stack.\r
// Then set the VM's IP to new EBC code.\r
//\r
- VmPtr->R[0] -= 8;\r
- VmWriteMemN (VmPtr, (UINTN) VmPtr->R[0], (UINTN) FramePtr);\r
- VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->R[0];\r
- VmPtr->R[0] -= 8;\r
- VmWriteMem64 (VmPtr, (UINTN) VmPtr->R[0], (UINT64) (UINTN) (VmPtr->Ip + Size));\r
+ VmPtr->Gpr[0] -= 8;\r
+ 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) (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
+ // The callee is not a thunk to EBC, call native code,\r
+ // and get return value.\r
//\r
- EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr);\r
- \r
+ VmPtr->Gpr[7] = EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr);\r
+\r
//\r
- // Get return value and advance the IP.\r
+ // Advance the IP.\r
//\r
- VmPtr->R[7] = EbcLLGetReturnValue ();\r
VmPtr->Ip += Size;\r
}\r
}\r
\r
-STATIC\r
+\r
+/**\r
+ Begin executing an EBC image.\r
+\r
+ This is a thunk function. Microsoft x64 compiler only provide fast_call\r
+ calling convention, so the first four arguments are passed by rcx, rdx,\r
+ r8, and r9, while other arguments are passed in stack.\r
+\r
+ @param EntryPoint The entrypoint of EBC code.\r
+ @param Arg1 The 1st argument.\r
+ @param Arg2 The 2nd argument.\r
+ @param Arg3 The 3rd argument.\r
+ @param Arg4 The 4th argument.\r
+ @param Arg5 The 5th argument.\r
+ @param Arg6 The 6th argument.\r
+ @param Arg7 The 7th argument.\r
+ @param Arg8 The 8th argument.\r
+ @param Arg9 The 9th argument.\r
+ @param Arg10 The 10th argument.\r
+ @param Arg11 The 11th argument.\r
+ @param Arg12 The 12th argument.\r
+ @param Arg13 The 13th argument.\r
+ @param Arg14 The 14th argument.\r
+ @param Arg15 The 15th argument.\r
+ @param Arg16 The 16th argument.\r
+\r
+ @return The value returned by the EBC application we're going to run.\r
+\r
+**/\r
UINT64\r
+EFIAPI\r
EbcInterpret (\r
- IN OUT UINTN Arg1,\r
- IN OUT UINTN Arg2,\r
- IN OUT UINTN Arg3,\r
- IN OUT UINTN Arg4,\r
- IN OUT UINTN Arg5,\r
- IN OUT UINTN Arg6,\r
- IN OUT UINTN Arg7,\r
- IN OUT UINTN Arg8,\r
- IN OUT UINTN Arg9,\r
- IN OUT UINTN Arg10,\r
- IN OUT UINTN Arg11,\r
- IN OUT UINTN Arg12,\r
- IN OUT UINTN Arg13,\r
- IN OUT UINTN Arg14,\r
- IN OUT UINTN Arg15,\r
- IN OUT UINTN Arg16\r
+ IN UINTN EntryPoint,\r
+ IN UINTN Arg1,\r
+ IN UINTN Arg2,\r
+ IN UINTN Arg3,\r
+ IN UINTN Arg4,\r
+ IN UINTN Arg5,\r
+ IN UINTN Arg6,\r
+ IN UINTN Arg7,\r
+ IN UINTN Arg8,\r
+ IN UINTN Arg9,\r
+ IN UINTN Arg10,\r
+ IN UINTN Arg11,\r
+ IN UINTN Arg12,\r
+ IN UINTN Arg13,\r
+ IN UINTN Arg14,\r
+ IN UINTN Arg15,\r
+ IN UINTN Arg16\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Begin executing an EBC image. The address of the entry point is passed\r
- in via a processor register, so we'll need to make a call to get the\r
- value.\r
- \r
-Arguments:\r
-\r
- None. Since we're called from a fixed up thunk (which we want to keep\r
- small), our only so-called argument is the EBC entry point passed in\r
- to us in a processor register.\r
-\r
-Returns:\r
-\r
- The value returned by the EBC application we're going to run.\r
- \r
---*/\r
{\r
//\r
// Create a new VM context on the stack\r
UINTN StackIndex;\r
\r
//\r
- // Get the EBC entry point from the processor register.\r
+ // Get the EBC entry point\r
//\r
- Addr = EbcLLGetEbcEntryPoint ();\r
+ Addr = EntryPoint;\r
\r
//\r
// Now clear out our context\r
return Status;\r
}\r
VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
- VmContext.R[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
- VmContext.HighStackBottom = (UINTN)VmContext.R[0];\r
- VmContext.R[0] &= ~(sizeof (UINTN) - 1);\r
- VmContext.R[0] -= sizeof (UINTN);\r
+ VmContext.Gpr[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
+ VmContext.HighStackBottom = (UINTN)VmContext.Gpr[0];\r
+ VmContext.Gpr[0] &= ~((VM_REGISTER)(sizeof (UINTN) - 1));\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
\r
//\r
// Put a magic value in the stack gap, then adjust down again\r
//\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE;\r
- VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0];\r
- VmContext.LowStackTop = (UINTN) VmContext.R[0];\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;\r
+ VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];\r
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];\r
\r
//\r
// For IA32, this is where we say our return address is\r
//\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg16;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg15;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg14;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg13;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg12;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg11;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg10;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg9;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg8;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg7;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg6;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg5;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg4;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg3;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg2;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg1;\r
- VmContext.R[0] -= 16;\r
- VmContext.StackRetAddr = (UINT64) VmContext.R[0];\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg16;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg15;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg14;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg13;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg12;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg11;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg10;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg9;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg8;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg7;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg6;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg5;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg4;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg3;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg2;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) Arg1;\r
+ VmContext.Gpr[0] -= 16;\r
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];\r
\r
//\r
// We need to keep track of where the EBC stack starts. This way, if the EBC\r
//\r
// Begin executing the EBC code\r
//\r
+ EbcDebuggerHookEbcInterpret (&VmContext);\r
EbcExecute (&VmContext);\r
\r
//\r
- // Return the value in R[7] unless there was an error\r
+ // Return the value in Gpr[7] unless there was an error\r
//\r
ReturnEBCStack(StackIndex);\r
- return (UINT64) VmContext.R[7];\r
+ return (UINT64) VmContext.Gpr[7];\r
}\r
\r
-STATIC\r
+\r
+/**\r
+ Begin executing an EBC image.\r
+\r
+ @param EntryPoint The entrypoint of EBC code.\r
+ @param ImageHandle image handle for the EBC application we're executing\r
+ @param SystemTable standard system table passed into an driver's entry\r
+ point\r
+\r
+ @return The value returned by the EBC application we're going to run.\r
+\r
+**/\r
UINT64\r
+EFIAPI\r
ExecuteEbcImageEntryPoint (\r
+ IN UINTN EntryPoint,\r
IN EFI_HANDLE ImageHandle,\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Begin executing an EBC image. The address of the entry point is passed\r
- in via a processor register, so we'll need to make a call to get the\r
- value.\r
- \r
-Arguments:\r
-\r
- ImageHandle - image handle for the EBC application we're executing\r
- SystemTable - standard system table passed into an driver's entry point\r
-\r
-Returns:\r
-\r
- The value returned by the EBC application we're going to run.\r
-\r
---*/\r
{\r
//\r
// Create a new VM context on the stack\r
UINTN StackIndex;\r
\r
//\r
- // Get the EBC entry point from the processor register. Make sure you don't\r
- // call any functions before this or you could mess up the register the\r
- // entry point is passed in.\r
+ // Get the EBC entry point\r
//\r
- Addr = EbcLLGetEbcEntryPoint ();\r
+ Addr = EntryPoint;\r
\r
- //\r
- // Print(L"*** Thunked into EBC entry point - ImageHandle = 0x%X\n", (UINTN)ImageHandle);\r
- // Print(L"EBC entry point is 0x%X\n", (UINT32)(UINTN)Addr);\r
//\r
// Now clear out our context\r
//\r
return Status;\r
}\r
VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
- VmContext.R[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
- VmContext.HighStackBottom = (UINTN)VmContext.R[0];\r
- VmContext.R[0] -= sizeof (UINTN);\r
- \r
+ VmContext.Gpr[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
+ VmContext.HighStackBottom = (UINTN)VmContext.Gpr[0];\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+\r
//\r
// Put a magic value in the stack gap, then adjust down again\r
//\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE;\r
- VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0];\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) VM_STACK_KEY_VALUE;\r
+ VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.Gpr[0];\r
\r
//\r
// Align the stack on a natural boundary\r
- // VmContext.R[0] &= ~(sizeof(UINTN) - 1);\r
+ // VmContext.Gpr[0] &= ~(sizeof(UINTN) - 1);\r
//\r
- VmContext.LowStackTop = (UINTN) VmContext.R[0];\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) SystemTable;\r
- VmContext.R[0] -= sizeof (UINTN);\r
- *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) ImageHandle;\r
+ VmContext.LowStackTop = (UINTN) VmContext.Gpr[0];\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) SystemTable;\r
+ VmContext.Gpr[0] -= sizeof (UINTN);\r
+ *(UINTN *) (UINTN) (VmContext.Gpr[0]) = (UINTN) ImageHandle;\r
\r
- VmContext.R[0] -= 16; \r
- VmContext.StackRetAddr = (UINT64) VmContext.R[0];\r
+ VmContext.Gpr[0] -= 16;\r
+ VmContext.StackRetAddr = (UINT64) VmContext.Gpr[0];\r
//\r
// VM pushes 16-bytes for return address. Simulate that here.\r
//\r
//\r
// Begin executing the EBC code\r
//\r
+ EbcDebuggerHookExecuteEbcImageEntryPoint (&VmContext);\r
EbcExecute (&VmContext);\r
\r
//\r
- // Return the value in R[7] unless there was an error\r
+ // Return the value in Gpr[7] unless there was an error\r
//\r
- return (UINT64) VmContext.R[7];\r
+ ReturnEBCStack(StackIndex);\r
+ return (UINT64) VmContext.Gpr[7];\r
}\r
\r
+\r
+/**\r
+ Create thunks for an EBC image entry point, or an EBC protocol service.\r
+\r
+ @param ImageHandle Image handle for the EBC image. If not null, then\r
+ we're creating a thunk for an image entry point.\r
+ @param EbcEntryPoint Address of the EBC code that the thunk is to call\r
+ @param Thunk Returned thunk we create here\r
+ @param Flags Flags indicating options for creating the thunk\r
+\r
+ @retval EFI_SUCCESS The thunk was created successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter of EbcEntryPoint is not 16-bit\r
+ aligned.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to created the EBC\r
+ Thunk.\r
+ @retval EFI_BUFFER_TOO_SMALL EBC_THUNK_SIZE is not larger enough.\r
+\r
+**/\r
EFI_STATUS\r
EbcCreateThunks (\r
IN EFI_HANDLE ImageHandle,\r
OUT VOID **Thunk,\r
IN UINT32 Flags\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Create an IA32 thunk for the given EBC entry point.\r
- \r
-Arguments:\r
-\r
- ImageHandle - Handle of image for which this thunk is being created\r
- EbcEntryPoint - Address of the EBC code that the thunk is to call\r
- Thunk - Returned thunk we create here\r
-\r
-Returns:\r
-\r
- Standard EFI status.\r
- \r
---*/\r
{\r
UINT8 *Ptr;\r
UINT8 *ThunkBase;\r
- UINT32 I;\r
- UINT32 Addr;\r
- INT32 Size;\r
+ UINT32 Index;\r
INT32 ThunkSize;\r
\r
//\r
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 = EbcAllocatePoolForThunk (sizeof(mInstructionBufferTemplate));\r
\r
if (Ptr == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
*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
- //\r
- *Ptr = 0xB8;\r
- Ptr++;\r
- Size--;\r
- Addr = (UINT32) 0xCA112EBC;\r
- for (I = 0; I < sizeof (Addr); I++) {\r
- *Ptr = (UINT8) (UINTN) Addr;\r
- Addr >>= 8;\r
- Ptr++;\r
- Size--;\r
- }\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
- //\r
- *Ptr = 0xB8;\r
- Ptr++;\r
- Size--;\r
- Addr = (UINT32) EbcEntryPoint;\r
- for (I = 0; I < sizeof (Addr); I++) {\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
+ // Copy whole thunk instruction buffer template\r
//\r
- if (Flags & FLAG_THUNK_ENTRY_POINT) {\r
- Addr = (UINT32) (UINTN) ExecuteEbcImageEntryPoint;\r
- } else {\r
- Addr = (UINT32) (UINTN) EbcInterpret;\r
- }\r
+ CopyMem (Ptr, mInstructionBufferTemplate, sizeof(mInstructionBufferTemplate));\r
\r
//\r
- // MOV ecx\r
+ // Patch EbcEntryPoint and EbcLLEbcInterpret\r
//\r
- *Ptr = 0xB9;\r
- Ptr++;\r
- Size--;\r
- for (I = 0; I < sizeof (Addr); I++) {\r
- *Ptr = (UINT8) Addr;\r
- Addr >>= 8;\r
- Ptr++;\r
- Size--;\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
- // 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