]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1. Advance IP in case of Break(3) in breakpoint exception
authorqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 30 Mar 2007 08:44:55 +0000 (08:44 +0000)
committerqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 30 Mar 2007 08:44:55 +0000 (08:44 +0000)
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

13 files changed:
EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c
EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h
EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c
EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h
EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.S
EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm
EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c
EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s
EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c
EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.h
EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.S
EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm
EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c

index 4b020cb6daa7ff4d6fe0126f3ba38c2094ca8c9f..174e774de3087d81f3be5529346f88093b5ca1a7 100644 (file)
@@ -22,11 +22,6 @@ Abstract:
 #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
@@ -763,10 +758,15 @@ Returns:
       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
@@ -1122,10 +1122,6 @@ Returns:
       EXCEPTION_FLAG_NONE,\r
       VmPtr\r
       );\r
-    //\r
-    // Don't advance the IP\r
-    //\r
-    return EFI_UNSUPPORTED;\r
     break;\r
 \r
   //\r
@@ -4504,19 +4500,8 @@ Returns:
   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
index 1783ef4e83d957e7c1abeac2369fffef304b532d..b1926ee975c85cec099c3b49371fee552cf501cf 100644 (file)
@@ -24,6 +24,12 @@ Abstract:
 #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
index 52f8d9fad787b5d68bde2633fe3bde230d5cd25f..b42ff170560992b05d32ce7b7981334ddf1baa08 100644 (file)
@@ -178,6 +178,10 @@ static EFI_PERIODIC_CALLBACK  mDebugPeriodicCallback
 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
@@ -288,6 +292,12 @@ Returns:
       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
@@ -335,6 +345,7 @@ Returns:
   return EFI_SUCCESS;\r
 \r
 ErrorExit:\r
+  FreeEBCStack();\r
   HandleBuffer  = NULL;\r
   Status = gBS->LocateHandleBuffer (\r
                   ByProtocol,\r
@@ -504,7 +515,7 @@ Routine Description:
 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
@@ -867,6 +878,7 @@ Returns:
   // 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
@@ -1020,6 +1032,87 @@ EbcGetVersion (
   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
index 5ccf8e11c73349035ea647ac6355c27d4f9373df..6926a90029eae46e4ac59a57844c628f44ed2e53 100644 (file)
@@ -49,6 +49,8 @@ typedef struct {
   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
@@ -106,6 +108,8 @@ EbcDebugSignalException (
 //\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
@@ -152,6 +156,32 @@ EbcLLGetReturnValue (
   )\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
index 712cac2ece1838bbe107f5195694ae8826af834e..2df0f0c3e0ed636956de7fb9546860abac6efe94 100644 (file)
 #*  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):
index b485bc9fd2d75d9c9783ae2994fc97def6f877cb..4249241e7d7077ed980eef200425ee6642b13186 100644 (file)
@@ -2,7 +2,7 @@
   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
@@ -45,6 +45,7 @@
 ;---------------------------------------------------------------------------\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
@@ -81,6 +95,7 @@ _EbcLLCALLEXNative        PROC    NEAR    PUBLIC
 \r
       ; Standard function epilog\r
       mov      esp, ebp\r
+      pop      ebx\r
       pop      ebp\r
       ret\r
 _EbcLLCALLEXNative    ENDP\r
index ab054493418e844ab6c8a5bfef8125a51b86d042..a534e0078081067386af4b7f1372e03ddcf0a691 100644 (file)
@@ -32,6 +32,7 @@ Abstract:
 #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
@@ -152,7 +153,15 @@ EbcInterpret (
   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
@@ -179,6 +188,8 @@ Returns:
   //\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
@@ -194,33 +205,72 @@ Returns:
   // 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
@@ -235,7 +285,7 @@ Returns:
   // 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
@@ -244,6 +294,7 @@ Returns:
   //\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
@@ -277,6 +328,8 @@ Returns:
   //\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
@@ -308,26 +361,40 @@ Returns:
   // 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
index fe2ca3f572a00c2463a9b90185afea06db3b3d70..e329b68e66eb8d5942b175adf99fc9b9522fba0b 100644 (file)
@@ -40,6 +40,7 @@ name::
          mov ar##.##pfs=loc1 ;;\\r
          br##.##ret##.##dpnt  b0;;\r
 \r
+.type CopyMem, @function;  \r
 \r
 //-----------------------------------------------------------------------------\r
 //++\r
@@ -126,6 +127,35 @@ PROCEDURE_ENTRY(EbcAsmLLCALLEX)
 \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
index d60ab09d8a0630ec2abcec56a277999716f13c4c..3647a12fae6e602f0f02da82b419749a5363462a 100644 (file)
@@ -61,6 +61,8 @@ EbcInterpret (
   //\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
@@ -69,7 +71,14 @@ EbcInterpret (
   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
@@ -87,7 +96,14 @@ EbcInterpret (
   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
@@ -100,7 +116,6 @@ EbcInterpret (
   // 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
@@ -122,13 +137,21 @@ EbcInterpret (
   // 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
@@ -136,6 +159,14 @@ EbcInterpret (
   // 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
@@ -159,6 +190,7 @@ EbcInterpret (
   //\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
@@ -194,6 +226,8 @@ Returns:
   //\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
@@ -222,14 +256,21 @@ Returns:
   // 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
@@ -275,6 +316,7 @@ Returns:
   //\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
@@ -825,49 +867,3 @@ Action:
     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
index 93c568edc1f96c59e5a5fbe1581cc865daf80190..f6c929ba3ee579fdb0bec572e4d3fcada3d1a9c1 100644 (file)
@@ -27,6 +27,7 @@ Revision History
 #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
index 61322a3264c6d2c0c9d439f56b9b422d75c0709b..d9f638643af49b8f37fafab3f006c821308e4456 100644 (file)
@@ -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.
index 59394621ba2b5e4d8e57af22dcfd2b2dd0b4fc6f..7b59e93aa1f935a498f0aac05bd499073368b9f0 100644 (file)
@@ -49,7 +49,11 @@ text SEGMENT
 ; 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
@@ -59,7 +63,12 @@ EbcLLCALLEXNative        PROC
       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
@@ -92,7 +101,7 @@ EbcLLCALLEXNative    ENDP
 ; 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
@@ -115,7 +124,7 @@ EbcLLGetEbcEntryPoint    ENDP
 ;--*/\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
@@ -136,7 +145,7 @@ EbcLLGetStackPointer    ENDP
 ; 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
index cad5c6a43bf27df296115631420d3c0511c6ae45..bec82d67c519fd8cdd9fef0ec346cf029386b2a1 100644 (file)
@@ -32,6 +32,8 @@ Abstract:
 #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
@@ -71,7 +73,18 @@ EbcInterpret (
   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
@@ -98,6 +111,8 @@ Returns:
   //\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
@@ -125,8 +140,15 @@ Returns:
   //\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
@@ -148,6 +170,18 @@ Returns:
   // 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
@@ -178,7 +212,6 @@ Returns:
   // 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
@@ -188,6 +221,7 @@ Returns:
   //\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
@@ -221,6 +255,8 @@ Returns:
   //\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
@@ -250,8 +286,16 @@ Returns:
   // 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
@@ -287,7 +331,6 @@ Returns:
   // 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
@@ -297,6 +340,7 @@ Returns:
   //\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