#include "EbcInt.h"\r
#include "EbcExecute.h"\r
\r
-//\r
-// VM major/minor version\r
-//\r
-#define VM_MAJOR_VERSION 1\r
-#define VM_MINOR_VERSION 0\r
\r
//\r
// Define some useful data size constants to allow switch statements based on\r
EbcDebugSignalException (EXCEPT_EBC_STACK_FAULT, EXCEPTION_FLAG_FATAL, VmPtr);\r
StackCorrupted = 1;\r
}\r
+ if (!StackCorrupted && ((UINT64)VmPtr->R[0] <= (UINT64)(UINTN) VmPtr->StackTop)) {\r
+ EbcDebugSignalException (EXCEPT_EBC_STACK_FAULT, EXCEPTION_FLAG_FATAL, VmPtr);\r
+ StackCorrupted = 1;\r
+ }\r
}\r
\r
Done:\r
mVmPtr = NULL;\r
+\r
return Status;\r
}\r
\r
EXCEPTION_FLAG_NONE,\r
VmPtr\r
);\r
- //\r
- // Don't advance the IP\r
- //\r
- return EFI_UNSUPPORTED;\r
break;\r
\r
//\r
adjust for the stack gap and return the modified address.\r
\r
--*/\r
-{\r
- if ((Addr >= VmPtr->LowStackTop) && (Addr < VmPtr->HighStackBottom)) {\r
- //\r
- // In the stack gap -- now make sure it's not in the VM itself, which\r
- // would be the case if it's accessing VM register contents.\r
- //\r
- if ((Addr < (UINTN) VmPtr) || (Addr > (UINTN) VmPtr + sizeof (VM_CONTEXT))) {\r
- VmPtr->LastAddrConverted = Addr;\r
- VmPtr->LastAddrConvertedValue = Addr - VmPtr->LowStackTop + VmPtr->HighStackBottom;\r
- return Addr - VmPtr->LowStackTop + VmPtr->HighStackBottom;\r
- }\r
- }\r
-\r
+{ \r
+ ASSERT(((Addr < VmPtr->LowStackTop) || (Addr > VmPtr->HighStackBottom)));\r
return Addr;\r
}\r
\r
#ifndef _EBC_EXECUTE_H_\r
#define _EBC_EXECUTE_H_\r
\r
+//\r
+// VM major/minor version\r
+//\r
+#define VM_MAJOR_VERSION 1\r
+#define VM_MINOR_VERSION 0\r
+\r
//\r
// Macros to check and set alignment\r
//\r
static EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};\r
static EFI_GUID mEfiEbcVmTestProtocolGuid = EFI_EBC_VM_TEST_PROTOCOL_GUID;\r
\r
+static VOID* mStackBuffer[MAX_STACK_NUM];\r
+static EFI_HANDLE mStackBufferIndex[MAX_STACK_NUM];\r
+static UINTN mStackNum = 0;\r
+\r
//\r
// Event for Periodic callback\r
//\r
return Status;\r
}\r
}\r
+\r
+ Status = InitEBCStack();\r
+ if (EFI_ERROR(Status)) {\r
+ goto ErrorExit;\r
+ }\r
+\r
//\r
// Allocate memory for our debug protocol. Then fill in the blanks.\r
//\r
return EFI_SUCCESS;\r
\r
ErrorExit:\r
+ FreeEBCStack();\r
HandleBuffer = NULL;\r
Status = gBS->LocateHandleBuffer (\r
ByProtocol,\r
Arguments:\r
\r
This - pointer to the caller's debug support protocol interface\r
- PeriodicCallback - pointer to the function to call periodically\r
+ ExceptionCallback - pointer to the function to the exception\r
\r
Returns:\r
\r
// First go through our list of known image handles and see if we've already\r
// created an image list element for this image handle.\r
//\r
+ ReturnEBCStackByHandle(ImageHandle);\r
PrevImageList = NULL;\r
for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
if (ImageList->ImageHandle == ImageHandle) {\r
return EFI_SUCCESS;\r
}\r
\r
+EFI_STATUS\r
+GetEBCStack(\r
+ EFI_HANDLE Handle,\r
+ VOID **StackBuffer,\r
+ UINTN *BufferIndex\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_TPL OldTpl;\r
+ OldTpl = gBS->RaiseTPL(EFI_TPL_HIGH_LEVEL);\r
+ for (Index = 0; Index < mStackNum; Index ++) {\r
+ if (mStackBufferIndex[Index] == NULL) {\r
+ mStackBufferIndex[Index] = Handle;\r
+ break;\r
+ }\r
+ }\r
+ gBS->RestoreTPL(OldTpl);\r
+ if (Index == mStackNum) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ *BufferIndex = Index;\r
+ *StackBuffer = mStackBuffer[Index];\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ReturnEBCStack(\r
+ UINTN Index\r
+ )\r
+{\r
+ mStackBufferIndex[Index] =NULL;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+ReturnEBCStackByHandle(\r
+ EFI_HANDLE Handle\r
+ )\r
+{\r
+ UINTN Index;\r
+ for (Index = 0; Index < mStackNum; Index ++) {\r
+ if (mStackBufferIndex[Index] == Handle) {\r
+ break;\r
+ }\r
+ }\r
+ if (Index == mStackNum) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ mStackBufferIndex[Index] = NULL;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitEBCStack (\r
+ VOID\r
+ )\r
+{\r
+ for (mStackNum = 0; mStackNum < MAX_STACK_NUM; mStackNum ++) {\r
+ mStackBuffer[mStackNum] = AllocatePool(STACK_POOL_SIZE);\r
+ mStackBufferIndex[mStackNum] = NULL;\r
+ if (mStackBuffer[mStackNum] == NULL) {\r
+ break;\r
+ }\r
+ }\r
+ if (mStackNum == 0) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FreeEBCStack(\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+ for (Index = 0; Index < mStackNum; Index ++) {\r
+ FreePool(mStackBuffer[Index]);\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
STATIC\r
EFI_STATUS\r
InitEbcVmTestProtocol (\r
VOID *FramePtr;\r
VOID *EntryPoint; // entry point of EBC image\r
UINTN ImageBase;\r
+ VOID *StackPool;\r
+ VOID *StackTop;\r
} VM_CONTEXT;\r
\r
extern VM_CONTEXT *mVmPtr;\r
//\r
#define EFI_TIMER_UNIT_1MS (1000 * 10)\r
#define EBC_VM_PERIODIC_CALLBACK_RATE (1000 * EFI_TIMER_UNIT_1MS)\r
+#define STACK_POOL_SIZE (1024 * 1020)\r
+#define MAX_STACK_NUM 4\r
\r
EFI_STATUS\r
EbcDebugSignalPeriodic (\r
)\r
;\r
\r
+EFI_STATUS\r
+GetEBCStack(\r
+ EFI_HANDLE Handle,\r
+ VOID **StackBuffer,\r
+ UINTN *BufferIndex\r
+ );\r
+\r
+EFI_STATUS\r
+ReturnEBCStack(\r
+ UINTN Index\r
+ );\r
+\r
+EFI_STATUS\r
+InitEBCStack (\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+FreeEBCStack(\r
+ VOID\r
+ );\r
+\r
+EFI_STATUS\r
+ReturnEBCStackByHandle(\r
+ EFI_HANDLE Handle\r
+ );\r
//\r
// Defines for a simple EBC debugger interface\r
//\r
#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#*
#****************************************************************************
+.globl ASM_PFX(CopyMem)
+
.globl ASM_PFX(EbcLLCALLEXNative)
ASM_PFX(EbcLLCALLEXNative):
- push %ebp
- mov %esp,%ebp
- mov 0x8(%esp),%ecx
- mov 0xc(%esp),%eax
- mov %eax,%esp
- call *%ecx
- mov %ebp,%esp
- mov %ebp,%esp
- pop %ebp
- ret
+ push %ebp\r
+ push %ebx\r
+ mov %esp,%ebp\r
+ mov 0xc(%esp),%ecx\r
+ mov 0x14(%esp),%eax\r
+ mov 0x10(%esp),%edx\r
+ sub %edx,%eax\r
+ sub %eax,%esp\r
+ mov %esp,%ebx\r
+ push %ecx\r
+ push %eax\r
+ push %edx\r
+ push %ebx\r
+ call ASM_PFX(CopyMem)\r
+ pop %eax\r
+ pop %eax\r
+ pop %eax\r
+ pop %ecx\r
+ call *%ecx\r
+ mov %ebp,%esp\r
+ mov %ebp,%esp\r
+ pop %ebx\r
+ pop %ebp\r
+ ret \r
.globl ASM_PFX(EbcLLGetEbcEntryPoint)
ASM_PFX(EbcLLGetEbcEntryPoint):
title VM ASSEMBLY LANGUAGE ROUTINES\r
;****************************************************************************\r
;* \r
-;* Copyright (c) 2006, Intel Corporation \r
+;* Copyright (c) 2006 - 2007, 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
;---------------------------------------------------------------------------\r
;;GenericPostSegment SEGMENT USE16\r
;---------------------------------------------------------------------------\r
+CopyMem PROTO C Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD\r
\r
;****************************************************************************\r
; EbcLLCALLEXNative\r
; VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)\r
_EbcLLCALLEXNative PROC NEAR PUBLIC\r
push ebp\r
+ push ebx\r
mov ebp, esp ; standard function prolog\r
\r
; Get function address in a register\r
; mov ecx, FuncAddr => mov ecx, dword ptr [FuncAddr]\r
- mov ecx, dword ptr [esp]+8\r
-\r
+ mov ecx, dword ptr [esp]+0Ch\r
+ \r
; Set stack pointer to new value\r
; mov eax, NewStackPointer => mov eax, dword ptr [NewSp]\r
- mov eax, dword ptr [esp] + 0Ch\r
- mov esp, eax \r
+ mov eax, dword ptr [esp] + 14h\r
+ mov edx, dword ptr [esp] + 10h\r
+ sub eax, edx\r
+ sub esp, eax \r
+ mov ebx, esp\r
+ push ecx\r
+ push eax\r
+ push edx\r
+ push ebx\r
+ call CopyMem\r
+ pop eax\r
+ pop eax\r
+ pop eax\r
+ pop ecx\r
\r
; Now call the external routine\r
call ecx\r
\r
; Standard function epilog\r
mov esp, ebp\r
+ pop ebx\r
pop ebp\r
ret\r
_EbcLLCALLEXNative ENDP\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 OUT UINTN Arg5,\r
IN OUT UINTN Arg6,\r
IN OUT UINTN Arg7,\r
- IN OUT UINTN Arg8\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
)\r
/*++\r
\r
//\r
VM_CONTEXT VmContext;\r
UINTN Addr;\r
+ EFI_STATUS Status;\r
+ UINTN StackIndex;\r
\r
//\r
// Get the EBC entry point from the processor register.\r
// Set the VM instruction pointer to the correct location in memory.\r
//\r
VmContext.Ip = (VMIP) Addr;\r
-\r
//\r
// Initialize the stack pointer for the EBC. Get the current system stack\r
// pointer and adjust it down by the max needed for the interpreter.\r
//\r
- Addr = EbcLLGetStackPointer ();\r
-\r
- VmContext.R[0] = (UINT64) Addr;\r
- VmContext.R[0] -= VM_STACK_SIZE;\r
\r
//\r
// Align the stack on a natural boundary\r
//\r
+\r
+ //\r
+ // Allocate stack pool\r
+ //\r
+ Status = GetEBCStack((EFI_HANDLE)-1, &VmContext.StackPool, &StackIndex);\r
+ if (EFI_ERROR(Status)) {\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
\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.R[0] -= sizeof (UINTN);\r
+ VmContext.LowStackTop = (UINTN) VmContext.R[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.LowStackTop = (UINTN) VmContext.R[0];\r
\r
//\r
// We need to keep track of where the EBC stack starts. This way, if the EBC\r
// the stack too, so adjust accordingly.\r
// VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) + sizeof (Addr));\r
//\r
- VmContext.HighStackBottom = (UINTN) &Arg1 - 16;\r
+\r
//\r
// Begin executing the EBC code\r
//\r
//\r
// Return the value in R[7] unless there was an error\r
//\r
+ ReturnEBCStack(StackIndex);\r
return (UINT64) VmContext.R[7];\r
}\r
\r
//\r
VM_CONTEXT VmContext;\r
UINTN Addr;\r
+ EFI_STATUS Status;\r
+ UINTN StackIndex;\r
\r
//\r
// Get the EBC entry point from the processor register. Make sure you don't\r
// Initialize the stack pointer for the EBC. Get the current system stack\r
// pointer and adjust it down by the max needed for the interpreter.\r
//\r
- Addr = EbcLLGetStackPointer ();\r
- VmContext.R[0] = (UINT64) Addr;\r
- VmContext.R[0] -= VM_STACK_SIZE;\r
+\r
+ //\r
+ // Allocate stack pool\r
+ //\r
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);\r
+ if (EFI_ERROR(Status)) {\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
//\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.R[0] -= sizeof (UINTN);\r
\r
//\r
// Align the stack on a natural boundary\r
// VmContext.R[0] &= ~(sizeof(UINTN) - 1);\r
//\r
- VmContext.StackRetAddr = (UINT64) VmContext.R[0];\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
+\r
+ VmContext.R[0] -= 16; \r
+ VmContext.StackRetAddr = (UINT64) VmContext.R[0];\r
//\r
// VM pushes 16-bytes for return address. Simulate that here.\r
//\r
- VmContext.HighStackBottom = (UINTN) &ImageHandle - 16;\r
\r
//\r
// Begin executing the EBC code\r
mov ar##.##pfs=loc1 ;;\\r
br##.##ret##.##dpnt b0;;\r
\r
+.type CopyMem, @function; \r
\r
//-----------------------------------------------------------------------------\r
//++\r
\r
PROCEDURE_EXIT(EbcAsmLLCALLEX)\r
\r
+PROCEDURE_ENTRY(EbcLLCALLEXNative)\r
+ NESTED_SETUP (3,6,3,0)\r
+ \r
+ mov loc2 = in2;;\r
+ mov loc3 = in1;;\r
+ sub loc2 = loc2, loc3\r
+ mov loc4 = r12;;\r
+ or loc5 = r1, r0\r
+ \r
+ sub r12 = r12, loc2\r
+ mov out2 = loc2;;\r
+\r
+ and r12 = -0x10, r12\r
+ mov out1 = in1;;\r
+ mov out0 = r12;;\r
+ adds r12 = -0x8, r12\r
+ (p0) br.call.dptk.many b0 = CopyMem;;\r
+ adds r12 = 0x8, r12\r
+ \r
+ mov out0 = in0;;\r
+ mov out1 = r12;;\r
+ (p0) br.call.dptk.many b0 = EbcAsmLLCALLEX;;\r
+ mov r12 = loc4;;\r
+ or r1 = loc5, r0\r
+ \r
+ NESTED_RETURN\r
+PROCEDURE_EXIT(EbcLLCALLEXNative)\r
+\r
+\r
//\r
// UINTN EbcLLGetEbcEntryPoint(VOID)\r
//\r
//\r
VM_CONTEXT VmContext;\r
UINTN Addr;\r
+ EFI_STATUS Status;\r
+ UINTN StackIndex;\r
VA_LIST List;\r
UINT64 Arg2;\r
UINT64 Arg3;\r
UINT64 Arg6;\r
UINT64 Arg7;\r
UINT64 Arg8;\r
- UINTN Arg9Addr;\r
+ UINT64 Arg9;\r
+ UINT64 Arg10;\r
+ UINT64 Arg11;\r
+ UINT64 Arg12;\r
+ UINT64 Arg13;\r
+ UINT64 Arg14;\r
+ UINT64 Arg15;\r
+ UINT64 Arg16;\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
Arg6 = VA_ARG (List, UINT64);\r
Arg7 = VA_ARG (List, UINT64);\r
Arg8 = VA_ARG (List, UINT64);\r
- Arg9Addr = (UINTN) List;\r
+ Arg9 = VA_ARG (List, UINT64);\r
+ Arg10 = VA_ARG (List, UINT64);\r
+ Arg11 = VA_ARG (List, UINT64);\r
+ Arg12 = VA_ARG (List, UINT64);\r
+ Arg13 = VA_ARG (List, UINT64);\r
+ Arg14 = VA_ARG (List, UINT64);\r
+ Arg15 = VA_ARG (List, UINT64);\r
+ Arg16 = VA_ARG (List, UINT64);\r
//\r
// Now clear out our context\r
//\r
// Initialize the stack pointer for the EBC. Get the current system stack\r
// pointer and adjust it down by the max needed for the interpreter.\r
//\r
- Addr = (UINTN) Arg9Addr;\r
//\r
// NOTE: Eventually we should have the interpreter allocate memory\r
// for stack space which it will use during its execution. This\r
// actually trying to access args9 and greater. Therefore we need to\r
// adjust memory accesses in this region to point above the stack gap.\r
//\r
- VmContext.HighStackBottom = (UINTN) Addr;\r
//\r
// Now adjust the EBC stack pointer down to leave a gap for interpreter\r
// execution. Then stuff a magic value there.\r
//\r
- VmContext.R[0] = (UINT64) Addr;\r
- VmContext.R[0] -= VM_STACK_SIZE;\r
+ \r
+ Status = GetEBCStack((EFI_HANDLE)(UINTN)-1, &VmContext.StackPool, &StackIndex);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];\r
+ VmContext.R[0] -= sizeof (UINTN);\r
+\r
+ \r
PushU64 (&VmContext, (UINT64) VM_STACK_KEY_VALUE);\r
VmContext.StackMagicPtr = (UINTN *) VmContext.R[0];\r
VmContext.LowStackTop = (UINTN) VmContext.R[0];\r
// Push the EBC arguments on the stack. Does not matter that they may not\r
// all be valid.\r
//\r
+ PushU64 (&VmContext, Arg16);\r
+ PushU64 (&VmContext, Arg15);\r
+ PushU64 (&VmContext, Arg14);\r
+ PushU64 (&VmContext, Arg13);\r
+ PushU64 (&VmContext, Arg12);\r
+ PushU64 (&VmContext, Arg11);\r
+ PushU64 (&VmContext, Arg10);\r
+ PushU64 (&VmContext, Arg9);\r
PushU64 (&VmContext, Arg8);\r
PushU64 (&VmContext, Arg7);\r
PushU64 (&VmContext, Arg6);\r
//\r
// Return the value in R[7] unless there was an error\r
//\r
+ ReturnEBCStack(StackIndex);\r
return (UINT64) VmContext.R[7];\r
}\r
\r
//\r
VM_CONTEXT VmContext;\r
UINTN Addr;\r
+ EFI_STATUS Status;\r
+ UINTN StackIndex;\r
\r
//\r
// Get the EBC entry point from the processor register. Make sure you don't\r
// Get the stack pointer. This is the bottom of the upper stack.\r
//\r
Addr = EbcLLGetStackPointer ();\r
- VmContext.HighStackBottom = (UINTN) Addr;\r
- VmContext.R[0] = (INT64) Addr;\r
+ \r
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];\r
+ VmContext.R[0] -= sizeof (UINTN);\r
\r
+ \r
//\r
// Allocate stack space for the interpreter. Then put a magic value\r
// at the bottom so we can detect stack corruption.\r
//\r
- VmContext.R[0] -= VM_STACK_SIZE;\r
PushU64 (&VmContext, (UINT64) VM_STACK_KEY_VALUE);\r
VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0];\r
\r
//\r
// Return the value in R[7] unless there was an error\r
//\r
+ ReturnEBCStack(StackIndex);\r
return (UINT64) VmContext.R[7];\r
}\r
\r
VmPtr->Ip += Size;\r
}\r
}\r
-\r
-VOID\r
-EbcLLCALLEXNative (\r
- IN UINTN CallAddr,\r
- IN UINTN EbcSp,\r
- IN VOID *FramePtr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
- Implements the EBC CALLEX instruction to call an external function, which\r
- seems to be native code.\r
-\r
- We'll copy the entire EBC stack frame down below itself in memory and use\r
- that copy for passing parameters. \r
-\r
-Arguments:\r
- CallAddr - address (function pointer) of function to call\r
- EbcSp - current EBC stack pointer\r
- FramePtr - current EBC frame pointer.\r
-\r
-Returns:\r
- NA\r
-\r
---*/\r
-{\r
- UINTN FrameSize;\r
- VOID *Destination;\r
- VOID *Source;\r
- //\r
- // The stack for an EBC function looks like this:\r
- // FramePtr (8)\r
- // RetAddr (8)\r
- // Locals (n)\r
- // Stack for passing args (m)\r
- //\r
- // Pad the frame size with 64 bytes because the low-level code we call\r
- // will move the stack pointer up assuming worst-case 8 args in registers.\r
- //\r
- FrameSize = (UINTN) FramePtr - (UINTN) EbcSp + 64;\r
- Source = (VOID *) EbcSp;\r
- Destination = (VOID *) ((UINT8 *) EbcSp - FrameSize - CPU_STACK_ALIGNMENT);\r
- Destination = (VOID *) ((UINTN) ((UINTN) Destination + CPU_STACK_ALIGNMENT - 1) &~((UINTN) CPU_STACK_ALIGNMENT - 1));\r
- CopyMem (Destination, Source, FrameSize);\r
- EbcAsmLLCALLEX ((UINTN) CallAddr, (UINTN) Destination);\r
-}\r
#define VM_STACK_SIZE (1024 * 32)\r
\r
#define EBC_THUNK_SIZE 128\r
+#define STACK_REMAIN_SIZE (1024 * 4)\r
\r
//\r
// For code execution, thunks must be aligned on 16-byte boundary\r
#
# Destroys no working registers.
#****************************************************************************
+.global _CopyMem;
+
# VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
.global _EbcLLCALLEXNative;
_EbcLLCALLEXNative:
mov %rcx, %rbx
# Set stack pointer to new value
- mov %rdx, %rsp
+ sub %r8, %rdx
+ sub %rsp, %r8
+ mov %rsp, %rcx
+ sub %rsp, 0x20
+ call _CopyMem
+ add %rsp, 0x20
# Considering the worst case, load 4 potiential arguments
# into registers.
; Destroys no working registers.\r
;****************************************************************************\r
; VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)\r
-EbcLLCALLEXNative PROC\r
+\r
+CopyMem PROTO Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD\r
+\r
+\r
+EbcLLCALLEXNative PROC NEAR PUBLIC\r
push rbp\r
push rbx\r
mov rbp, rsp\r
mov rbx, rcx\r
\r
; Set stack pointer to new value\r
- mov rsp, rdx \r
+ sub r8, rdx\r
+ sub rsp, r8\r
+ mov rcx, rsp\r
+ sub rsp, 20h\r
+ call CopyMem \r
+ add rsp, 20h\r
\r
; Considering the worst case, load 4 potiential arguments\r
; into registers.\r
; Returns:\r
; The contents of the register in which the entry point is passed.\r
;\r
-EbcLLGetEbcEntryPoint PROC\r
+EbcLLGetEbcEntryPoint PROC NEAR PUBLIC\r
ret\r
EbcLLGetEbcEntryPoint ENDP\r
\r
;--*/\r
\r
; UINTN EbcLLGetStackPointer() \r
-EbcLLGetStackPointer PROC\r
+EbcLLGetStackPointer PROC NEAR PUBLIC\r
mov rax, rsp ; get current stack pointer\r
; Stack adjusted by this much when we were called,\r
; For this function, it's 4.\r
; Returns:\r
; The unmodified value returned by the native code.\r
;\r
-EbcLLGetReturnValue PROC\r
+EbcLLGetReturnValue PROC NEAR PUBLIC\r
ret\r
EbcLLGetReturnValue ENDP\r
\r
#define VM_STACK_SIZE (1024 * 8)\r
#define EBC_THUNK_SIZE 64\r
\r
+#define STACK_REMAIN_SIZE (1024 * 4)\r
+\r
STATIC\r
VOID\r
PushU64 (\r
UINTN Arg2,\r
UINTN Arg3,\r
UINTN Arg4,\r
- UINTN Arg5\r
+ UINTN Arg5,\r
+ UINTN Arg6,\r
+ UINTN Arg7,\r
+ UINTN Arg8,\r
+ UINTN Arg9,\r
+ UINTN Arg10,\r
+ UINTN Arg11,\r
+ UINTN Arg12,\r
+ UINTN Arg13,\r
+ UINTN Arg14,\r
+ UINTN Arg15,\r
+ UINTN Arg16\r
)\r
/*++\r
\r
//\r
VM_CONTEXT VmContext;\r
UINTN Addr;\r
+ EFI_STATUS Status;\r
+ UINTN StackIndex;\r
\r
//\r
// Get the EBC entry point from the processor register.\r
//\r
// Adjust the VM's stack pointer down.\r
//\r
- VmContext.R[0] = (UINT64) Addr;\r
- VmContext.R[0] -= VM_STACK_SIZE;\r
+ \r
+ Status = GetEBCStack((EFI_HANDLE)(UINTN)-1, &VmContext.StackPool, &StackIndex);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];\r
+ VmContext.R[0] -= sizeof (UINTN);\r
\r
//\r
// Align the stack on a natural boundary.\r
// For the worst case, assume there are 4 arguments passed in registers, store\r
// them to VM's stack.\r
//\r
+ PushU64 (&VmContext, (UINT64) Arg16);\r
+ PushU64 (&VmContext, (UINT64) Arg15);\r
+ PushU64 (&VmContext, (UINT64) Arg14);\r
+ PushU64 (&VmContext, (UINT64) Arg13);\r
+ PushU64 (&VmContext, (UINT64) Arg12);\r
+ PushU64 (&VmContext, (UINT64) Arg11);\r
+ PushU64 (&VmContext, (UINT64) Arg10);\r
+ PushU64 (&VmContext, (UINT64) Arg9);\r
+ PushU64 (&VmContext, (UINT64) Arg8);\r
+ PushU64 (&VmContext, (UINT64) Arg7);\r
+ PushU64 (&VmContext, (UINT64) Arg6);\r
+ PushU64 (&VmContext, (UINT64) Arg5);\r
PushU64 (&VmContext, (UINT64) Arg4);\r
PushU64 (&VmContext, (UINT64) Arg3);\r
PushU64 (&VmContext, (UINT64) Arg2);\r
// the stack too, so adjust accordingly.\r
// VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) + sizeof (Addr));\r
//\r
- VmContext.HighStackBottom = (UINTN) &Arg5;\r
\r
//\r
// Begin executing the EBC code\r
//\r
// Return the value in R[7] unless there was an error\r
//\r
+ ReturnEBCStack(StackIndex);\r
return (UINT64) VmContext.R[7];\r
}\r
\r
//\r
VM_CONTEXT VmContext;\r
UINTN Addr;\r
+ EFI_STATUS Status;\r
+ UINTN StackIndex;\r
\r
//\r
// Get the EBC entry point from the processor register. Make sure you don't\r
// pointer and adjust it down by the max needed for the interpreter.\r
//\r
Addr = EbcLLGetStackPointer ();\r
- VmContext.R[0] = (UINT64) Addr;\r
- VmContext.R[0] -= VM_STACK_SIZE;\r
+\r
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);\r
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);\r
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];\r
+ VmContext.R[0] -= sizeof (UINTN);\r
+\r
\r
//\r
// Put a magic value in the stack gap, then adjust down again\r
// Entry function needn't access high stack context, simply\r
// put the stack pointer here.\r
//\r
- VmContext.HighStackBottom = (UINTN) Addr;\r
\r
//\r
// Begin executing the EBC code\r
//\r
// Return the value in R[7] unless there was an error\r
//\r
+ ReturnEBCStack(StackIndex);\r
return (UINT64) VmContext.R[7];\r
}\r
\r