summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>2007-03-30 08:44:55 +0000
committerqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>2007-03-30 08:44:55 +0000
commit73ebf379a4bd48c69befdd8439ac9be952a5814f (patch)
tree6875528c1ca73168fc3e1eb3315abe700aaf7553
parent784220c3f79a1c66818ae4dcca2afe7db06a0351 (diff)
downloadedk2-platforms-73ebf379a4bd48c69befdd8439ac9be952a5814f.tar.xz
1. Advance IP in case of Break(3) in breakpoint exception
2. Add stack management algorithm to avoid pool allocation during EBC instruction interpretation. 3. Add multi EBC image support. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2519 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c29
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h6
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c95
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h30
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.S36
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm25
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c97
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s30
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c106
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.h1
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.S9
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm19
-rw-r--r--EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c58
13 files changed, 420 insertions, 121 deletions
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c
index 4b020cb6da..174e774de3 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c
+++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c
@@ -22,11 +22,6 @@ Abstract:
#include "EbcInt.h"
#include "EbcExecute.h"
-//
-// VM major/minor version
-//
-#define VM_MAJOR_VERSION 1
-#define VM_MINOR_VERSION 0
//
// Define some useful data size constants to allow switch statements based on
@@ -763,10 +758,15 @@ Returns:
EbcDebugSignalException (EXCEPT_EBC_STACK_FAULT, EXCEPTION_FLAG_FATAL, VmPtr);
StackCorrupted = 1;
}
+ if (!StackCorrupted && ((UINT64)VmPtr->R[0] <= (UINT64)(UINTN) VmPtr->StackTop)) {
+ EbcDebugSignalException (EXCEPT_EBC_STACK_FAULT, EXCEPTION_FLAG_FATAL, VmPtr);
+ StackCorrupted = 1;
+ }
}
Done:
mVmPtr = NULL;
+
return Status;
}
@@ -1122,10 +1122,6 @@ Returns:
EXCEPTION_FLAG_NONE,
VmPtr
);
- //
- // Don't advance the IP
- //
- return EFI_UNSUPPORTED;
break;
//
@@ -4504,19 +4500,8 @@ Returns:
adjust for the stack gap and return the modified address.
--*/
-{
- if ((Addr >= VmPtr->LowStackTop) && (Addr < VmPtr->HighStackBottom)) {
- //
- // In the stack gap -- now make sure it's not in the VM itself, which
- // would be the case if it's accessing VM register contents.
- //
- if ((Addr < (UINTN) VmPtr) || (Addr > (UINTN) VmPtr + sizeof (VM_CONTEXT))) {
- VmPtr->LastAddrConverted = Addr;
- VmPtr->LastAddrConvertedValue = Addr - VmPtr->LowStackTop + VmPtr->HighStackBottom;
- return Addr - VmPtr->LowStackTop + VmPtr->HighStackBottom;
- }
- }
-
+{
+ ASSERT(((Addr < VmPtr->LowStackTop) || (Addr > VmPtr->HighStackBottom)));
return Addr;
}
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h
index 1783ef4e83..b1926ee975 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h
+++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h
@@ -25,6 +25,12 @@ Abstract:
#define _EBC_EXECUTE_H_
//
+// VM major/minor version
+//
+#define VM_MAJOR_VERSION 1
+#define VM_MINOR_VERSION 0
+
+//
// Macros to check and set alignment
//
#define ASSERT_ALIGNED(addr, size) ASSERT (!((UINT32) (addr) & (size - 1)))
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c
index 52f8d9fad7..b42ff17056 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c
+++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c
@@ -178,6 +178,10 @@ static EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
static EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};
static EFI_GUID mEfiEbcVmTestProtocolGuid = EFI_EBC_VM_TEST_PROTOCOL_GUID;
+static VOID* mStackBuffer[MAX_STACK_NUM];
+static EFI_HANDLE mStackBufferIndex[MAX_STACK_NUM];
+static UINTN mStackNum = 0;
+
//
// Event for Periodic callback
//
@@ -288,6 +292,12 @@ Returns:
return Status;
}
}
+
+ Status = InitEBCStack();
+ if (EFI_ERROR(Status)) {
+ goto ErrorExit;
+ }
+
//
// Allocate memory for our debug protocol. Then fill in the blanks.
//
@@ -335,6 +345,7 @@ Returns:
return EFI_SUCCESS;
ErrorExit:
+ FreeEBCStack();
HandleBuffer = NULL;
Status = gBS->LocateHandleBuffer (
ByProtocol,
@@ -504,7 +515,7 @@ Routine Description:
Arguments:
This - pointer to the caller's debug support protocol interface
- PeriodicCallback - pointer to the function to call periodically
+ ExceptionCallback - pointer to the function to the exception
Returns:
@@ -867,6 +878,7 @@ Returns:
// First go through our list of known image handles and see if we've already
// created an image list element for this image handle.
//
+ ReturnEBCStackByHandle(ImageHandle);
PrevImageList = NULL;
for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {
if (ImageList->ImageHandle == ImageHandle) {
@@ -1020,6 +1032,87 @@ EbcGetVersion (
return EFI_SUCCESS;
}
+EFI_STATUS
+GetEBCStack(
+ EFI_HANDLE Handle,
+ VOID **StackBuffer,
+ UINTN *BufferIndex
+ )
+{
+ UINTN Index;
+ EFI_TPL OldTpl;
+ OldTpl = gBS->RaiseTPL(EFI_TPL_HIGH_LEVEL);
+ for (Index = 0; Index < mStackNum; Index ++) {
+ if (mStackBufferIndex[Index] == NULL) {
+ mStackBufferIndex[Index] = Handle;
+ break;
+ }
+ }
+ gBS->RestoreTPL(OldTpl);
+ if (Index == mStackNum) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *BufferIndex = Index;
+ *StackBuffer = mStackBuffer[Index];
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReturnEBCStack(
+ UINTN Index
+ )
+{
+ mStackBufferIndex[Index] =NULL;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReturnEBCStackByHandle(
+ EFI_HANDLE Handle
+ )
+{
+ UINTN Index;
+ for (Index = 0; Index < mStackNum; Index ++) {
+ if (mStackBufferIndex[Index] == Handle) {
+ break;
+ }
+ }
+ if (Index == mStackNum) {
+ return EFI_NOT_FOUND;
+ }
+ mStackBufferIndex[Index] = NULL;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitEBCStack (
+ VOID
+ )
+{
+ for (mStackNum = 0; mStackNum < MAX_STACK_NUM; mStackNum ++) {
+ mStackBuffer[mStackNum] = AllocatePool(STACK_POOL_SIZE);
+ mStackBufferIndex[mStackNum] = NULL;
+ if (mStackBuffer[mStackNum] == NULL) {
+ break;
+ }
+ }
+ if (mStackNum == 0) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FreeEBCStack(
+ VOID
+ )
+{
+ UINTN Index;
+ for (Index = 0; Index < mStackNum; Index ++) {
+ FreePool(mStackBuffer[Index]);
+ }
+ return EFI_SUCCESS;
+}
STATIC
EFI_STATUS
InitEbcVmTestProtocol (
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h
index 5ccf8e11c7..6926a90029 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h
+++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h
@@ -49,6 +49,8 @@ typedef struct {
VOID *FramePtr;
VOID *EntryPoint; // entry point of EBC image
UINTN ImageBase;
+ VOID *StackPool;
+ VOID *StackTop;
} VM_CONTEXT;
extern VM_CONTEXT *mVmPtr;
@@ -106,6 +108,8 @@ EbcDebugSignalException (
//
#define EFI_TIMER_UNIT_1MS (1000 * 10)
#define EBC_VM_PERIODIC_CALLBACK_RATE (1000 * EFI_TIMER_UNIT_1MS)
+#define STACK_POOL_SIZE (1024 * 1020)
+#define MAX_STACK_NUM 4
EFI_STATUS
EbcDebugSignalPeriodic (
@@ -152,6 +156,32 @@ EbcLLGetReturnValue (
)
;
+EFI_STATUS
+GetEBCStack(
+ EFI_HANDLE Handle,
+ VOID **StackBuffer,
+ UINTN *BufferIndex
+ );
+
+EFI_STATUS
+ReturnEBCStack(
+ UINTN Index
+ );
+
+EFI_STATUS
+InitEBCStack (
+ VOID
+ );
+
+EFI_STATUS
+FreeEBCStack(
+ VOID
+ );
+
+EFI_STATUS
+ReturnEBCStackByHandle(
+ EFI_HANDLE Handle
+ );
//
// Defines for a simple EBC debugger interface
//
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.S b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.S
index 712cac2ece..2df0f0c3e0 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.S
+++ b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.S
@@ -10,18 +10,34 @@
#* 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
+ push %ebx
+ mov %esp,%ebp
+ mov 0xc(%esp),%ecx
+ mov 0x14(%esp),%eax
+ mov 0x10(%esp),%edx
+ sub %edx,%eax
+ sub %eax,%esp
+ mov %esp,%ebx
+ push %ecx
+ push %eax
+ push %edx
+ push %ebx
+ call ASM_PFX(CopyMem)
+ pop %eax
+ pop %eax
+ pop %eax
+ pop %ecx
+ call *%ecx
+ mov %ebp,%esp
+ mov %ebp,%esp
+ pop %ebx
+ pop %ebp
+ ret
.globl ASM_PFX(EbcLLGetEbcEntryPoint)
ASM_PFX(EbcLLGetEbcEntryPoint):
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm
index b485bc9fd2..4249241e7d 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm
+++ b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm
@@ -2,7 +2,7 @@
title VM ASSEMBLY LANGUAGE ROUTINES
;****************************************************************************
;*
-;* Copyright (c) 2006, Intel Corporation
+;* Copyright (c) 2006 - 2007, Intel Corporation
;* All rights reserved. This program and the accompanying materials
;* are licensed and made available under the terms and conditions of the BSD License
;* which accompanies this distribution. The full text of the license may be found at
@@ -45,6 +45,7 @@
;---------------------------------------------------------------------------
;;GenericPostSegment SEGMENT USE16
;---------------------------------------------------------------------------
+CopyMem PROTO C Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD
;****************************************************************************
; EbcLLCALLEXNative
@@ -61,16 +62,29 @@
; VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
_EbcLLCALLEXNative PROC NEAR PUBLIC
push ebp
+ push ebx
mov ebp, esp ; standard function prolog
; Get function address in a register
; mov ecx, FuncAddr => mov ecx, dword ptr [FuncAddr]
- mov ecx, dword ptr [esp]+8
-
+ mov ecx, dword ptr [esp]+0Ch
+
; Set stack pointer to new value
; mov eax, NewStackPointer => mov eax, dword ptr [NewSp]
- mov eax, dword ptr [esp] + 0Ch
- mov esp, eax
+ mov eax, dword ptr [esp] + 14h
+ mov edx, dword ptr [esp] + 10h
+ sub eax, edx
+ sub esp, eax
+ mov ebx, esp
+ push ecx
+ push eax
+ push edx
+ push ebx
+ call CopyMem
+ pop eax
+ pop eax
+ pop eax
+ pop ecx
; Now call the external routine
call ecx
@@ -81,6 +95,7 @@ _EbcLLCALLEXNative PROC NEAR PUBLIC
; Standard function epilog
mov esp, ebp
+ pop ebx
pop ebp
ret
_EbcLLCALLEXNative ENDP
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c
index ab05449341..a534e00780 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c
+++ b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c
@@ -32,6 +32,7 @@ Abstract:
#define VM_STACK_SIZE (1024 * 4)
#define EBC_THUNK_SIZE 32
+#define STACK_REMAIN_SIZE (1024 * 4)
VOID
EbcLLCALLEX (
IN VM_CONTEXT *VmPtr,
@@ -152,7 +153,15 @@ EbcInterpret (
IN OUT UINTN Arg5,
IN OUT UINTN Arg6,
IN OUT UINTN Arg7,
- IN OUT UINTN Arg8
+ IN OUT UINTN Arg8,
+ IN OUT UINTN Arg9,
+ IN OUT UINTN Arg10,
+ IN OUT UINTN Arg11,
+ IN OUT UINTN Arg12,
+ IN OUT UINTN Arg13,
+ IN OUT UINTN Arg14,
+ IN OUT UINTN Arg15,
+ IN OUT UINTN Arg16
)
/*++
@@ -179,6 +188,8 @@ Returns:
//
VM_CONTEXT VmContext;
UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
//
// Get the EBC entry point from the processor register.
@@ -194,33 +205,72 @@ Returns:
// Set the VM instruction pointer to the correct location in memory.
//
VmContext.Ip = (VMIP) Addr;
-
//
// Initialize the stack pointer for the EBC. Get the current system stack
// pointer and adjust it down by the max needed for the interpreter.
//
- Addr = EbcLLGetStackPointer ();
-
- VmContext.R[0] = (UINT64) Addr;
- VmContext.R[0] -= VM_STACK_SIZE;
//
// Align the stack on a natural boundary
//
+
+ //
+ // Allocate stack pool
+ //
+ Status = GetEBCStack((EFI_HANDLE)-1, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.R[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN)VmContext.R[0];
VmContext.R[0] &= ~(sizeof (UINTN) - 1);
+ VmContext.R[0] -= sizeof (UINTN);
//
// Put a magic value in the stack gap, then adjust down again
//
*(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE;
VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0];
- VmContext.R[0] -= sizeof (UINTN);
+ VmContext.LowStackTop = (UINTN) VmContext.R[0];
//
// For IA32, this is where we say our return address is
//
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg16;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg15;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg14;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg13;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg12;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg11;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg10;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg9;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg8;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg7;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg6;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg5;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg4;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg3;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg2;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) Arg1;
+ VmContext.R[0] -= 16;
VmContext.StackRetAddr = (UINT64) VmContext.R[0];
- VmContext.LowStackTop = (UINTN) VmContext.R[0];
//
// We need to keep track of where the EBC stack starts. This way, if the EBC
@@ -235,7 +285,7 @@ Returns:
// the stack too, so adjust accordingly.
// VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) + sizeof (Addr));
//
- VmContext.HighStackBottom = (UINTN) &Arg1 - 16;
+
//
// Begin executing the EBC code
//
@@ -244,6 +294,7 @@ Returns:
//
// Return the value in R[7] unless there was an error
//
+ ReturnEBCStack(StackIndex);
return (UINT64) VmContext.R[7];
}
@@ -277,6 +328,8 @@ Returns:
//
VM_CONTEXT VmContext;
UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
//
// Get the EBC entry point from the processor register. Make sure you don't
@@ -308,26 +361,40 @@ Returns:
// Initialize the stack pointer for the EBC. Get the current system stack
// pointer and adjust it down by the max needed for the interpreter.
//
- Addr = EbcLLGetStackPointer ();
- VmContext.R[0] = (UINT64) Addr;
- VmContext.R[0] -= VM_STACK_SIZE;
+
+ //
+ // Allocate stack pool
+ //
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.R[0] = (UINT64)(UINTN) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN)VmContext.R[0];
+ VmContext.R[0] -= sizeof (UINTN);
+
//
// Put a magic value in the stack gap, then adjust down again
//
*(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE;
VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0];
- VmContext.R[0] -= sizeof (UINTN);
//
// Align the stack on a natural boundary
// VmContext.R[0] &= ~(sizeof(UINTN) - 1);
//
- VmContext.StackRetAddr = (UINT64) VmContext.R[0];
VmContext.LowStackTop = (UINTN) VmContext.R[0];
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) SystemTable;
+ VmContext.R[0] -= sizeof (UINTN);
+ *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) ImageHandle;
+
+ VmContext.R[0] -= 16;
+ VmContext.StackRetAddr = (UINT64) VmContext.R[0];
//
// VM pushes 16-bytes for return address. Simulate that here.
//
- VmContext.HighStackBottom = (UINTN) &ImageHandle - 16;
//
// Begin executing the EBC code
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s
index fe2ca3f572..e329b68e66 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s
+++ b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s
@@ -40,6 +40,7 @@ name::
mov ar##.##pfs=loc1 ;;\
br##.##ret##.##dpnt b0;;
+.type CopyMem, @function;
//-----------------------------------------------------------------------------
//++
@@ -126,6 +127,35 @@ PROCEDURE_ENTRY(EbcAsmLLCALLEX)
PROCEDURE_EXIT(EbcAsmLLCALLEX)
+PROCEDURE_ENTRY(EbcLLCALLEXNative)
+ NESTED_SETUP (3,6,3,0)
+
+ mov loc2 = in2;;
+ mov loc3 = in1;;
+ sub loc2 = loc2, loc3
+ mov loc4 = r12;;
+ or loc5 = r1, r0
+
+ sub r12 = r12, loc2
+ mov out2 = loc2;;
+
+ and r12 = -0x10, r12
+ mov out1 = in1;;
+ mov out0 = r12;;
+ adds r12 = -0x8, r12
+ (p0) br.call.dptk.many b0 = CopyMem;;
+ adds r12 = 0x8, r12
+
+ mov out0 = in0;;
+ mov out1 = r12;;
+ (p0) br.call.dptk.many b0 = EbcAsmLLCALLEX;;
+ mov r12 = loc4;;
+ or r1 = loc5, r0
+
+ NESTED_RETURN
+PROCEDURE_EXIT(EbcLLCALLEXNative)
+
+
//
// UINTN EbcLLGetEbcEntryPoint(VOID)
//
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c
index d60ab09d8a..3647a12fae 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c
+++ b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c
@@ -61,6 +61,8 @@ EbcInterpret (
//
VM_CONTEXT VmContext;
UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
VA_LIST List;
UINT64 Arg2;
UINT64 Arg3;
@@ -69,7 +71,14 @@ EbcInterpret (
UINT64 Arg6;
UINT64 Arg7;
UINT64 Arg8;
- UINTN Arg9Addr;
+ UINT64 Arg9;
+ UINT64 Arg10;
+ UINT64 Arg11;
+ UINT64 Arg12;
+ UINT64 Arg13;
+ UINT64 Arg14;
+ UINT64 Arg15;
+ UINT64 Arg16;
//
// Get the EBC entry point from the processor register. Make sure you don't
// call any functions before this or you could mess up the register the
@@ -87,7 +96,14 @@ EbcInterpret (
Arg6 = VA_ARG (List, UINT64);
Arg7 = VA_ARG (List, UINT64);
Arg8 = VA_ARG (List, UINT64);
- Arg9Addr = (UINTN) List;
+ Arg9 = VA_ARG (List, UINT64);
+ Arg10 = VA_ARG (List, UINT64);
+ Arg11 = VA_ARG (List, UINT64);
+ Arg12 = VA_ARG (List, UINT64);
+ Arg13 = VA_ARG (List, UINT64);
+ Arg14 = VA_ARG (List, UINT64);
+ Arg15 = VA_ARG (List, UINT64);
+ Arg16 = VA_ARG (List, UINT64);
//
// Now clear out our context
//
@@ -100,7 +116,6 @@ EbcInterpret (
// Initialize the stack pointer for the EBC. Get the current system stack
// pointer and adjust it down by the max needed for the interpreter.
//
- Addr = (UINTN) Arg9Addr;
//
// NOTE: Eventually we should have the interpreter allocate memory
// for stack space which it will use during its execution. This
@@ -122,13 +137,21 @@ EbcInterpret (
// actually trying to access args9 and greater. Therefore we need to
// adjust memory accesses in this region to point above the stack gap.
//
- VmContext.HighStackBottom = (UINTN) Addr;
//
// Now adjust the EBC stack pointer down to leave a gap for interpreter
// execution. Then stuff a magic value there.
//
- VmContext.R[0] = (UINT64) Addr;
- VmContext.R[0] -= VM_STACK_SIZE;
+
+ Status = GetEBCStack((EFI_HANDLE)(UINTN)-1, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];
+ VmContext.R[0] -= sizeof (UINTN);
+
+
PushU64 (&VmContext, (UINT64) VM_STACK_KEY_VALUE);
VmContext.StackMagicPtr = (UINTN *) VmContext.R[0];
VmContext.LowStackTop = (UINTN) VmContext.R[0];
@@ -136,6 +159,14 @@ EbcInterpret (
// Push the EBC arguments on the stack. Does not matter that they may not
// all be valid.
//
+ PushU64 (&VmContext, Arg16);
+ PushU64 (&VmContext, Arg15);
+ PushU64 (&VmContext, Arg14);
+ PushU64 (&VmContext, Arg13);
+ PushU64 (&VmContext, Arg12);
+ PushU64 (&VmContext, Arg11);
+ PushU64 (&VmContext, Arg10);
+ PushU64 (&VmContext, Arg9);
PushU64 (&VmContext, Arg8);
PushU64 (&VmContext, Arg7);
PushU64 (&VmContext, Arg6);
@@ -159,6 +190,7 @@ EbcInterpret (
//
// Return the value in R[7] unless there was an error
//
+ ReturnEBCStack(StackIndex);
return (UINT64) VmContext.R[7];
}
@@ -194,6 +226,8 @@ Returns:
//
VM_CONTEXT VmContext;
UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
//
// Get the EBC entry point from the processor register. Make sure you don't
@@ -222,14 +256,21 @@ Returns:
// Get the stack pointer. This is the bottom of the upper stack.
//
Addr = EbcLLGetStackPointer ();
- VmContext.HighStackBottom = (UINTN) Addr;
- VmContext.R[0] = (INT64) Addr;
+
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];
+ VmContext.R[0] -= sizeof (UINTN);
+
//
// Allocate stack space for the interpreter. Then put a magic value
// at the bottom so we can detect stack corruption.
//
- VmContext.R[0] -= VM_STACK_SIZE;
PushU64 (&VmContext, (UINT64) VM_STACK_KEY_VALUE);
VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0];
@@ -275,6 +316,7 @@ Returns:
//
// Return the value in R[7] unless there was an error
//
+ ReturnEBCStack(StackIndex);
return (UINT64) VmContext.R[7];
}
@@ -825,49 +867,3 @@ Action:
VmPtr->Ip += Size;
}
}
-
-VOID
-EbcLLCALLEXNative (
- IN UINTN CallAddr,
- IN UINTN EbcSp,
- IN VOID *FramePtr
- )
-/*++
-
-Routine Description:
- Implements the EBC CALLEX instruction to call an external function, which
- seems to be native code.
-
- We'll copy the entire EBC stack frame down below itself in memory and use
- that copy for passing parameters.
-
-Arguments:
- CallAddr - address (function pointer) of function to call
- EbcSp - current EBC stack pointer
- FramePtr - current EBC frame pointer.
-
-Returns:
- NA
-
---*/
-{
- UINTN FrameSize;
- VOID *Destination;
- VOID *Source;
- //
- // The stack for an EBC function looks like this:
- // FramePtr (8)
- // RetAddr (8)
- // Locals (n)
- // Stack for passing args (m)
- //
- // Pad the frame size with 64 bytes because the low-level code we call
- // will move the stack pointer up assuming worst-case 8 args in registers.
- //
- FrameSize = (UINTN) FramePtr - (UINTN) EbcSp + 64;
- Source = (VOID *) EbcSp;
- Destination = (VOID *) ((UINT8 *) EbcSp - FrameSize - CPU_STACK_ALIGNMENT);
- Destination = (VOID *) ((UINTN) ((UINTN) Destination + CPU_STACK_ALIGNMENT - 1) &~((UINTN) CPU_STACK_ALIGNMENT - 1));
- CopyMem (Destination, Source, FrameSize);
- EbcAsmLLCALLEX ((UINTN) CallAddr, (UINTN) Destination);
-}
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.h b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.h
index 93c568edc1..f6c929ba3e 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.h
+++ b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.h
@@ -27,6 +27,7 @@ Revision History
#define VM_STACK_SIZE (1024 * 32)
#define EBC_THUNK_SIZE 128
+#define STACK_REMAIN_SIZE (1024 * 4)
//
// For code execution, thunks must be aligned on 16-byte boundary
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.S b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.S
index 61322a3264..d9f638643a 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.S
+++ b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.S
@@ -44,6 +44,8 @@
#
# Destroys no working registers.
#****************************************************************************
+.global _CopyMem;
+
# VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
.global _EbcLLCALLEXNative;
_EbcLLCALLEXNative:
@@ -56,7 +58,12 @@ _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.
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm
index 59394621ba..7b59e93aa1 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm
+++ b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm
@@ -49,7 +49,11 @@ text SEGMENT
; Destroys no working registers.
;****************************************************************************
; VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
-EbcLLCALLEXNative PROC
+
+CopyMem PROTO Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD
+
+
+EbcLLCALLEXNative PROC NEAR PUBLIC
push rbp
push rbx
mov rbp, rsp
@@ -59,7 +63,12 @@ EbcLLCALLEXNative PROC
mov rbx, rcx
; Set stack pointer to new value
- mov rsp, rdx
+ sub r8, rdx
+ sub rsp, r8
+ mov rcx, rsp
+ sub rsp, 20h
+ call CopyMem
+ add rsp, 20h
; Considering the worst case, load 4 potiential arguments
; into registers.
@@ -92,7 +101,7 @@ EbcLLCALLEXNative ENDP
; Returns:
; The contents of the register in which the entry point is passed.
;
-EbcLLGetEbcEntryPoint PROC
+EbcLLGetEbcEntryPoint PROC NEAR PUBLIC
ret
EbcLLGetEbcEntryPoint ENDP
@@ -115,7 +124,7 @@ EbcLLGetEbcEntryPoint ENDP
;--*/
; UINTN EbcLLGetStackPointer()
-EbcLLGetStackPointer PROC
+EbcLLGetStackPointer PROC NEAR PUBLIC
mov rax, rsp ; get current stack pointer
; Stack adjusted by this much when we were called,
; For this function, it's 4.
@@ -136,7 +145,7 @@ EbcLLGetStackPointer ENDP
; Returns:
; The unmodified value returned by the native code.
;
-EbcLLGetReturnValue PROC
+EbcLLGetReturnValue PROC NEAR PUBLIC
ret
EbcLLGetReturnValue ENDP
diff --git a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c
index cad5c6a43b..bec82d67c5 100644
--- a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c
+++ b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c
@@ -32,6 +32,8 @@ Abstract:
#define VM_STACK_SIZE (1024 * 8)
#define EBC_THUNK_SIZE 64
+#define STACK_REMAIN_SIZE (1024 * 4)
+
STATIC
VOID
PushU64 (
@@ -71,7 +73,18 @@ EbcInterpret (
UINTN Arg2,
UINTN Arg3,
UINTN Arg4,
- UINTN Arg5
+ UINTN Arg5,
+ UINTN Arg6,
+ UINTN Arg7,
+ UINTN Arg8,
+ UINTN Arg9,
+ UINTN Arg10,
+ UINTN Arg11,
+ UINTN Arg12,
+ UINTN Arg13,
+ UINTN Arg14,
+ UINTN Arg15,
+ UINTN Arg16
)
/*++
@@ -98,6 +111,8 @@ Returns:
//
VM_CONTEXT VmContext;
UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
//
// Get the EBC entry point from the processor register.
@@ -125,8 +140,15 @@ Returns:
//
// Adjust the VM's stack pointer down.
//
- VmContext.R[0] = (UINT64) Addr;
- VmContext.R[0] -= VM_STACK_SIZE;
+
+ Status = GetEBCStack((EFI_HANDLE)(UINTN)-1, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];
+ VmContext.R[0] -= sizeof (UINTN);
//
// Align the stack on a natural boundary.
@@ -148,6 +170,18 @@ Returns:
// For the worst case, assume there are 4 arguments passed in registers, store
// them to VM's stack.
//
+ PushU64 (&VmContext, (UINT64) Arg16);
+ PushU64 (&VmContext, (UINT64) Arg15);
+ PushU64 (&VmContext, (UINT64) Arg14);
+ PushU64 (&VmContext, (UINT64) Arg13);
+ PushU64 (&VmContext, (UINT64) Arg12);
+ PushU64 (&VmContext, (UINT64) Arg11);
+ PushU64 (&VmContext, (UINT64) Arg10);
+ PushU64 (&VmContext, (UINT64) Arg9);
+ PushU64 (&VmContext, (UINT64) Arg8);
+ PushU64 (&VmContext, (UINT64) Arg7);
+ PushU64 (&VmContext, (UINT64) Arg6);
+ PushU64 (&VmContext, (UINT64) Arg5);
PushU64 (&VmContext, (UINT64) Arg4);
PushU64 (&VmContext, (UINT64) Arg3);
PushU64 (&VmContext, (UINT64) Arg2);
@@ -178,7 +212,6 @@ Returns:
// the stack too, so adjust accordingly.
// VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) + sizeof (Addr));
//
- VmContext.HighStackBottom = (UINTN) &Arg5;
//
// Begin executing the EBC code
@@ -188,6 +221,7 @@ Returns:
//
// Return the value in R[7] unless there was an error
//
+ ReturnEBCStack(StackIndex);
return (UINT64) VmContext.R[7];
}
@@ -221,6 +255,8 @@ Returns:
//
VM_CONTEXT VmContext;
UINTN Addr;
+ EFI_STATUS Status;
+ UINTN StackIndex;
//
// Get the EBC entry point from the processor register. Make sure you don't
@@ -250,8 +286,16 @@ Returns:
// pointer and adjust it down by the max needed for the interpreter.
//
Addr = EbcLLGetStackPointer ();
- VmContext.R[0] = (UINT64) Addr;
- VmContext.R[0] -= VM_STACK_SIZE;
+
+ Status = GetEBCStack(ImageHandle, &VmContext.StackPool, &StackIndex);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ VmContext.StackTop = (UINT8*)VmContext.StackPool + (STACK_REMAIN_SIZE);
+ VmContext.R[0] = (UINT64) ((UINT8*)VmContext.StackPool + STACK_POOL_SIZE);
+ VmContext.HighStackBottom = (UINTN) VmContext.R[0];
+ VmContext.R[0] -= sizeof (UINTN);
+
//
// Put a magic value in the stack gap, then adjust down again
@@ -287,7 +331,6 @@ Returns:
// Entry function needn't access high stack context, simply
// put the stack pointer here.
//
- VmContext.HighStackBottom = (UINTN) Addr;
//
// Begin executing the EBC code
@@ -297,6 +340,7 @@ Returns:
//
// Return the value in R[7] unless there was an error
//
+ ReturnEBCStack(StackIndex);
return (UINT64) VmContext.R[7];
}