summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/Ebc
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 /EdkModulePkg/Universal/Ebc
parent784220c3f79a1c66818ae4dcca2afe7db06a0351 (diff)
downloadedk2-73ebf379a4bd48c69befdd8439ac9be952a5814f.zip
edk2-73ebf379a4bd48c69befdd8439ac9be952a5814f.tar.gz
edk2-73ebf379a4bd48c69befdd8439ac9be952a5814f.tar.bz2
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
Diffstat (limited to 'EdkModulePkg/Universal/Ebc')
-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 4b020cb..174e774 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 1783ef4..b1926ee 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 52f8d9f..b42ff17 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 5ccf8e1..6926a90 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 712cac2..2df0f0c 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 b485bc9..4249241 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 ab05449..a534e00 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 fe2ca3f..e329b68 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 d60ab09..3647a12 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 93c568e..f6c929b 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 61322a3..d9f6386 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 5939462..7b59e93 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 cad5c6a..bec82d6 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];
}