-/*++ \r
-\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+/** @file\r
+ Main routines for the EBC interpreter. Includes the initialization and\r
+ main interpreter routines.\r
\r
-Module Name: \r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
- EbcInt.h\r
- \r
-Abstract:\r
-\r
- Main routines for the EBC interpreter. Includes the initialization and\r
- main interpreter routines. \r
- \r
---*/\r
+**/\r
\r
#ifndef _EBC_INT_H_\r
#define _EBC_INT_H_\r
\r
-\r
-#include <PiDxe.h>\r
+#include <Uefi.h>\r
\r
#include <Protocol/DebugSupport.h>\r
#include <Protocol/Ebc.h>\r
+#include <Protocol/EbcVmTest.h>\r
+#include <Protocol/EbcSimpleDebugger.h>\r
+#include <Protocol/PeCoffImageEmulator.h>\r
\r
#include <Library/BaseLib.h>\r
+#include <Library/CacheMaintenanceLib.h>\r
#include <Library/DebugLib.h>\r
+#include <Library/PeCoffLib.h>\r
#include <Library/UefiDriverEntryPoint.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
\r
-typedef INT64 VM_REGISTER;\r
-typedef UINT8 *VMIP; // instruction pointer for the VM\r
-typedef UINT32 EXCEPTION_FLAGS;\r
+extern VM_CONTEXT *mVmPtr;\r
\r
-typedef struct {\r
- VM_REGISTER R[8]; // General purpose registers.\r
- UINT64 Flags; // Flags register:\r
- // 0 Set to 1 if the result of the last compare was true\r
- // 1 Set to 1 if stepping\r
- // 2..63 Reserved.\r
- VMIP Ip; // Instruction pointer.\r
- UINTN LastException; //\r
- EXCEPTION_FLAGS ExceptionFlags; // to keep track of exceptions\r
- UINT32 StopFlags;\r
- UINT32 CompilerVersion; // via break(6)\r
- UINTN HighStackBottom; // bottom of the upper stack\r
- UINTN LowStackTop; // top of the lower stack\r
- UINT64 StackRetAddr; // location of final return address on stack\r
- UINTN *StackMagicPtr; // pointer to magic value on stack to detect corruption\r
- EFI_HANDLE ImageHandle; // for this EBC driver\r
- EFI_SYSTEM_TABLE *SystemTable; // for debugging only\r
- UINTN LastAddrConverted; // for debug\r
- UINTN LastAddrConvertedValue; // for debug\r
- VOID *FramePtr;\r
- VOID *EntryPoint; // entry point of EBC image\r
- UINTN ImageBase;\r
- VOID *StackPool;\r
- VOID *StackTop;\r
-} VM_CONTEXT;\r
-\r
-extern VM_CONTEXT *mVmPtr;\r
-\r
-//\r
-// Bits of exception flags field of VM context\r
-//\r
-#define EXCEPTION_FLAG_FATAL 0x80000000 // can't continue\r
-#define EXCEPTION_FLAG_ERROR 0x40000000 // bad, but try to continue\r
-#define EXCEPTION_FLAG_WARNING 0x20000000 // harmless problem\r
-#define EXCEPTION_FLAG_NONE 0x00000000 // for normal return\r
//\r
// Flags passed to the internal create-thunks function.\r
//\r
//\r
#define VM_STACK_KEY_VALUE 0xDEADBEEF\r
\r
+/**\r
+ Create thunks for an EBC image entry point, or an EBC protocol service.\r
+\r
+ @param ImageHandle Image handle for the EBC image. If not null, then\r
+ we're creating a thunk for an image entry point.\r
+ @param EbcEntryPoint Address of the EBC code that the thunk is to call\r
+ @param Thunk Returned thunk we create here\r
+ @param Flags Flags indicating options for creating the thunk\r
+\r
+ @retval EFI_SUCCESS The thunk was created successfully.\r
+ @retval EFI_INVALID_PARAMETER The parameter of EbcEntryPoint is not 16-bit\r
+ aligned.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to created the EBC\r
+ Thunk.\r
+ @retval EFI_BUFFER_TOO_SMALL EBC_THUNK_SIZE is not larger enough.\r
+\r
+**/\r
EFI_STATUS\r
EbcCreateThunks (\r
- IN EFI_HANDLE ImageHandle,\r
- IN VOID *EbcEntryPoint,\r
- OUT VOID **Thunk,\r
- IN UINT32 Flags\r
- )\r
-;\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN VOID *EbcEntryPoint,\r
+ OUT VOID **Thunk,\r
+ IN UINT32 Flags\r
+ );\r
\r
-EFI_STATUS\r
-EbcAddImageThunk (\r
- IN EFI_HANDLE ImageHandle,\r
- IN VOID *ThunkBuffer,\r
- IN UINT32 ThunkSize\r
- )\r
-;\r
+/**\r
+ Add a thunk to our list of thunks for a given image handle.\r
+ Also flush the instruction cache since we've written thunk code\r
+ to memory that will be executed eventually.\r
\r
-//\r
-// The interpreter calls these when an exception is detected,\r
-// or as a periodic callback.\r
-//\r
+ @param ImageHandle The image handle to which the thunk is tied.\r
+ @param ThunkBuffer The buffer that has been created/allocated.\r
+ @param ThunkSize The size of the thunk memory allocated.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
EFI_STATUS\r
-EbcDebugSignalException (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN EXCEPTION_FLAGS ExceptionFlags,\r
- IN VM_CONTEXT *VmPtr\r
- )\r
-;\r
+EbcAddImageThunk (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN VOID *ThunkBuffer,\r
+ IN UINT32 ThunkSize\r
+ );\r
\r
//\r
// Define a constant of how often to call the debugger periodic callback\r
// function.\r
//\r
-#define EFI_TIMER_UNIT_1MS (1000 * 10)\r
-#define EBC_VM_PERIODIC_CALLBACK_RATE (1000 * EFI_TIMER_UNIT_1MS)\r
-#define STACK_POOL_SIZE (1024 * 1020)\r
-#define MAX_STACK_NUM 4\r
-\r
-EFI_STATUS\r
-EbcDebugSignalPeriodic (\r
- IN VM_CONTEXT *VmPtr\r
- )\r
-;\r
+#define EFI_TIMER_UNIT_1MS (1000 * 10)\r
+#define EBC_VM_PERIODIC_CALLBACK_RATE (1000 * EFI_TIMER_UNIT_1MS)\r
+#define STACK_POOL_SIZE (1024 * 1020)\r
+#define MAX_STACK_NUM 4\r
\r
//\r
// External low level functions that are native-processor dependent\r
//\r
+\r
+/**\r
+ The VM thunk code stuffs an EBC entry point into a processor\r
+ register. Since we can't use inline assembly to get it from\r
+ the interpreter C code, stuff it into the return value\r
+ register and return.\r
+\r
+ @return The contents of the register in which the entry point is passed.\r
+\r
+**/\r
UINTN\r
+EFIAPI\r
EbcLLGetEbcEntryPoint (\r
VOID\r
- )\r
-;\r
+ );\r
\r
-UINTN\r
-EbcLLGetStackPointer (\r
- VOID\r
- )\r
-;\r
+/**\r
+ This function is called to execute an EBC CALLEX instruction.\r
+ This instruction requires that we thunk out to external native\r
+ code. For x64, we switch stacks, copy the arguments to the stack\r
+ and jump to the specified function.\r
+ On return, we restore the stack pointer to its original location.\r
+ Destroys no working registers.\r
\r
-VOID\r
+ @param CallAddr The function address.\r
+ @param EbcSp The new EBC stack pointer.\r
+ @param FramePtr The frame pointer.\r
+\r
+ @return The unmodified value returned by the native code.\r
+\r
+**/\r
+INT64\r
+EFIAPI\r
EbcLLCALLEXNative (\r
- IN UINTN CallAddr,\r
- IN UINTN EbcSp,\r
- IN VOID *FramePtr\r
- )\r
-;\r
+ IN UINTN CallAddr,\r
+ IN UINTN EbcSp,\r
+ IN VOID *FramePtr\r
+ );\r
\r
+/**\r
+ This function is called to execute an EBC CALLEX instruction.\r
+ The function check the callee's content to see whether it is common native\r
+ code or a thunk to another piece of EBC code.\r
+ If the callee is common native code, use EbcLLCAllEXASM to manipulate,\r
+ otherwise, set the VM->IP to target EBC code directly to avoid another VM\r
+ be startup which cost time and stack space.\r
+\r
+ @param VmPtr Pointer to a VM context.\r
+ @param FuncAddr Callee's address\r
+ @param NewStackPointer New stack pointer after the call\r
+ @param FramePtr New frame pointer after the call\r
+ @param Size The size of call instruction\r
+\r
+**/\r
VOID\r
EbcLLCALLEX (\r
- IN VM_CONTEXT *VmPtr,\r
- IN UINTN CallAddr,\r
- IN UINTN EbcSp,\r
- IN VOID *FramePtr,\r
- IN UINT8 Size\r
- )\r
-;\r
+ IN VM_CONTEXT *VmPtr,\r
+ IN UINTN FuncAddr,\r
+ IN UINTN NewStackPointer,\r
+ IN VOID *FramePtr,\r
+ IN UINT8 Size\r
+ );\r
\r
-INT64\r
-EbcLLGetReturnValue (\r
- VOID\r
- )\r
-;\r
+/**\r
+ Returns the stack index and buffer assosicated with the Handle parameter.\r
+\r
+ @param Handle The EFI handle as the index to the EBC stack.\r
+ @param StackBuffer A pointer to hold the returned stack buffer.\r
+ @param BufferIndex A pointer to hold the returned stack index.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any\r
+ existing EBC stack.\r
+ @retval EFI_SUCCESS The stack index and buffer were found and\r
+ returned to the caller.\r
\r
+**/\r
EFI_STATUS\r
-GetEBCStack(\r
- EFI_HANDLE Handle,\r
- VOID **StackBuffer,\r
- UINTN *BufferIndex\r
+GetEBCStack (\r
+ IN EFI_HANDLE Handle,\r
+ OUT VOID **StackBuffer,\r
+ OUT UINTN *BufferIndex\r
);\r
\r
+/**\r
+ Returns from the EBC stack by stack Index.\r
+\r
+ @param Index Specifies which EBC stack to return from.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
EFI_STATUS\r
-ReturnEBCStack(\r
- UINTN Index\r
+ReturnEBCStack (\r
+ IN UINTN Index\r
);\r
\r
+/**\r
+ Allocates memory to hold all the EBC stacks.\r
+\r
+ @retval EFI_SUCCESS The EBC stacks were allocated successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.\r
+\r
+**/\r
EFI_STATUS\r
InitEBCStack (\r
VOID\r
);\r
\r
-EFI_STATUS\r
-FreeEBCStack(\r
- VOID\r
- );\r
+/**\r
+ Free all EBC stacks allocated before.\r
\r
-EFI_STATUS\r
-ReturnEBCStackByHandle(\r
- EFI_HANDLE Handle\r
- );\r
-//\r
-// Defines for a simple EBC debugger interface\r
-//\r
-typedef struct _EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL;\r
+ @retval EFI_SUCCESS All the EBC stacks were freed.\r
\r
-#define EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL_GUID \\r
- { \\r
- 0x2a72d11e, 0x7376, 0x40f6, { 0x9c, 0x68, 0x23, 0xfa, 0x2f, 0xe3, 0x63, 0xf1 } \\r
- }\r
-\r
-typedef\r
+**/\r
EFI_STATUS\r
-(*EBC_DEBUGGER_SIGNAL_EXCEPTION) (\r
- IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This,\r
- IN VM_CONTEXT * VmPtr,\r
- IN EFI_EXCEPTION_TYPE ExceptionType\r
+FreeEBCStack (\r
+ VOID\r
);\r
\r
-typedef\r
-VOID\r
-(*EBC_DEBUGGER_DEBUG) (\r
- IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This,\r
- IN VM_CONTEXT * VmPtr\r
- );\r
+/**\r
+ Returns from the EBC stack associated with the Handle parameter.\r
\r
-typedef\r
-UINT32\r
-(*EBC_DEBUGGER_DASM) (\r
- IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This,\r
- IN VM_CONTEXT * VmPtr,\r
- IN UINT16 *DasmString OPTIONAL,\r
- IN UINT32 DasmStringSize\r
- );\r
+ @param Handle Specifies the EFI handle to find the EBC stack with.\r
\r
-//\r
-// This interface allows you to configure the EBC debug support\r
-// driver. For example, turn on or off saving and printing of\r
-// delta VM even if called. Or to even disable the entire interface,\r
-// in which case all functions become no-ops.\r
-//\r
-typedef\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
EFI_STATUS\r
-(*EBC_DEBUGGER_CONFIGURE) (\r
- IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This,\r
- IN UINT32 ConfigId,\r
- IN UINTN ConfigValue\r
+ReturnEBCStackByHandle (\r
+ IN EFI_HANDLE Handle\r
);\r
\r
-//\r
-// Prototype for the actual EBC debug support protocol interface\r
-//\r
-struct _EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL {\r
- EBC_DEBUGGER_DEBUG Debugger;\r
- EBC_DEBUGGER_SIGNAL_EXCEPTION SignalException;\r
- EBC_DEBUGGER_DASM Dasm;\r
- EBC_DEBUGGER_CONFIGURE Configure;\r
-};\r
-\r
typedef struct {\r
- EFI_EBC_PROTOCOL *This;\r
- VOID *EntryPoint;\r
- EFI_HANDLE ImageHandle;\r
- VM_CONTEXT VmContext;\r
+ EFI_EBC_PROTOCOL *This;\r
+ VOID *EntryPoint;\r
+ EFI_HANDLE ImageHandle;\r
+ VM_CONTEXT VmContext;\r
} EFI_EBC_THUNK_DATA;\r
\r
-#define EBC_PROTOCOL_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('e', 'b', 'c', 'p')\r
-\r
-struct _EBC_PROTOCOL_PRIVATE_DATA {\r
- UINT32 Signature;\r
- EFI_EBC_PROTOCOL EbcProtocol;\r
- UINTN StackBase;\r
- UINTN StackTop;\r
- UINTN StackSize;\r
-} ;\r
+#define EBC_PROTOCOL_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('e', 'b', 'c', 'p')\r
\r
#define EBC_PROTOCOL_PRIVATE_DATA_FROM_THIS(a) \\r
CR(a, EBC_PROTOCOL_PRIVATE_DATA, EbcProtocol, EBC_PROTOCOL_PRIVATE_DATA_SIGNATURE)\r
\r
+/**\r
+ Allocates a buffer of type EfiBootServicesCode.\r
+\r
+ @param AllocationSize The number of bytes to allocate.\r
+\r
+ @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+EbcAllocatePoolForThunk (\r
+ IN UINTN AllocationSize\r
+ );\r
\r
#endif // #ifndef _EBC_INT_H_\r