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