1 /** @file 2 Main routines for the EBC interpreter. Includes the initialization and 3 main interpreter routines. 4 5 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #ifndef _EBC_INT_H_ 17 #define _EBC_INT_H_ 18 19 20 #include <Uefi.h> 21 22 #include <Protocol/DebugSupport.h> 23 #include <Protocol/Ebc.h> 24 #include <Protocol/EbcVmTest.h> 25 #include <Protocol/EbcSimpleDebugger.h> 26 27 #include <Library/BaseLib.h> 28 #include <Library/DebugLib.h> 29 #include <Library/UefiDriverEntryPoint.h> 30 #include <Library/BaseMemoryLib.h> 31 #include <Library/UefiBootServicesTableLib.h> 32 #include <Library/MemoryAllocationLib.h> 33 34 extern VM_CONTEXT *mVmPtr; 35 36 // 37 // Bits of exception flags field of VM context 38 // 39 #define EXCEPTION_FLAG_FATAL 0x80000000 // can't continue 40 #define EXCEPTION_FLAG_ERROR 0x40000000 // bad, but try to continue 41 #define EXCEPTION_FLAG_WARNING 0x20000000 // harmless problem 42 #define EXCEPTION_FLAG_NONE 0x00000000 // for normal return 43 // 44 // Flags passed to the internal create-thunks function. 45 // 46 #define FLAG_THUNK_ENTRY_POINT 0x01 // thunk for an image entry point 47 #define FLAG_THUNK_PROTOCOL 0x00 // thunk for an EBC protocol service 48 // 49 // Put this value at the bottom of the VM's stack gap so we can check it on 50 // occasion to make sure the stack has not been corrupted. 51 // 52 #define VM_STACK_KEY_VALUE 0xDEADBEEF 53 54 /** 55 Create thunks for an EBC image entry point, or an EBC protocol service. 56 57 @param ImageHandle Image handle for the EBC image. If not null, then 58 we're creating a thunk for an image entry point. 59 @param EbcEntryPoint Address of the EBC code that the thunk is to call 60 @param Thunk Returned thunk we create here 61 @param Flags Flags indicating options for creating the thunk 62 63 @retval EFI_SUCCESS The thunk was created successfully. 64 @retval EFI_INVALID_PARAMETER The parameter of EbcEntryPoint is not 16-bit 65 aligned. 66 @retval EFI_OUT_OF_RESOURCES There is not enough memory to created the EBC 67 Thunk. 68 @retval EFI_BUFFER_TOO_SMALL EBC_THUNK_SIZE is not larger enough. 69 70 **/ 71 EFI_STATUS 72 EbcCreateThunks ( 73 IN EFI_HANDLE ImageHandle, 74 IN VOID *EbcEntryPoint, 75 OUT VOID **Thunk, 76 IN UINT32 Flags 77 ); 78 79 /** 80 Add a thunk to our list of thunks for a given image handle. 81 Also flush the instruction cache since we've written thunk code 82 to memory that will be executed eventually. 83 84 @param ImageHandle The image handle to which the thunk is tied. 85 @param ThunkBuffer The buffer that has been created/allocated. 86 @param ThunkSize The size of the thunk memory allocated. 87 88 @retval EFI_OUT_OF_RESOURCES Memory allocation failed. 89 @retval EFI_SUCCESS The function completed successfully. 90 91 **/ 92 EFI_STATUS 93 EbcAddImageThunk ( 94 IN EFI_HANDLE ImageHandle, 95 IN VOID *ThunkBuffer, 96 IN UINT32 ThunkSize 97 ); 98 99 // 100 // The interpreter calls these when an exception is detected, 101 // or as a periodic callback. 102 // 103 /** 104 The VM interpreter calls this function when an exception is detected. 105 106 @param ExceptionType Specifies the processor exception detected. 107 @param ExceptionFlags Specifies the exception context. 108 @param VmPtr Pointer to a VM context for passing info to the 109 EFI debugger. 110 111 @retval EFI_SUCCESS This function completed successfully. 112 113 **/ 114 EFI_STATUS 115 EbcDebugSignalException ( 116 IN EFI_EXCEPTION_TYPE ExceptionType, 117 IN EXCEPTION_FLAGS ExceptionFlags, 118 IN VM_CONTEXT *VmPtr 119 ); 120 121 // 122 // Define a constant of how often to call the debugger periodic callback 123 // function. 124 // 125 #define EFI_TIMER_UNIT_1MS (1000 * 10) 126 #define EBC_VM_PERIODIC_CALLBACK_RATE (1000 * EFI_TIMER_UNIT_1MS) 127 #define STACK_POOL_SIZE (1024 * 1020) 128 #define MAX_STACK_NUM 4 129 130 // 131 // External low level functions that are native-processor dependent 132 // 133 /** 134 The VM thunk code stuffs an EBC entry point into a processor 135 register. Since we can't use inline assembly to get it from 136 the interpreter C code, stuff it into the return value 137 register and return. 138 139 @return The contents of the register in which the entry point is passed. 140 141 **/ 142 UINTN 143 EFIAPI 144 EbcLLGetEbcEntryPoint ( 145 VOID 146 ); 147 148 /** 149 This function is called to execute an EBC CALLEX instruction. 150 This instruction requires that we thunk out to external native 151 code. For x64, we switch stacks, copy the arguments to the stack 152 and jump to the specified function. 153 On return, we restore the stack pointer to its original location. 154 Destroys no working registers. 155 156 @param CallAddr The function address. 157 @param EbcSp The new EBC stack pointer. 158 @param FramePtr The frame pointer. 159 160 @return The unmodified value returned by the native code. 161 162 **/ 163 INT64 164 EFIAPI 165 EbcLLCALLEXNative ( 166 IN UINTN CallAddr, 167 IN UINTN EbcSp, 168 IN VOID *FramePtr 169 ); 170 171 /** 172 This function is called to execute an EBC CALLEX instruction. 173 The function check the callee's content to see whether it is common native 174 code or a thunk to another piece of EBC code. 175 If the callee is common native code, use EbcLLCAllEXASM to manipulate, 176 otherwise, set the VM->IP to target EBC code directly to avoid another VM 177 be startup which cost time and stack space. 178 179 @param VmPtr Pointer to a VM context. 180 @param FuncAddr Callee's address 181 @param NewStackPointer New stack pointer after the call 182 @param FramePtr New frame pointer after the call 183 @param Size The size of call instruction 184 185 **/ 186 VOID 187 EbcLLCALLEX ( 188 IN VM_CONTEXT *VmPtr, 189 IN UINTN FuncAddr, 190 IN UINTN NewStackPointer, 191 IN VOID *FramePtr, 192 IN UINT8 Size 193 ); 194 195 /** 196 Returns the stack index and buffer assosicated with the Handle parameter. 197 198 @param Handle The EFI handle as the index to the EBC stack. 199 @param StackBuffer A pointer to hold the returned stack buffer. 200 @param BufferIndex A pointer to hold the returned stack index. 201 202 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any 203 existing EBC stack. 204 @retval EFI_SUCCESS The stack index and buffer were found and 205 returned to the caller. 206 207 **/ 208 EFI_STATUS 209 GetEBCStack( 210 IN EFI_HANDLE Handle, 211 OUT VOID **StackBuffer, 212 OUT UINTN *BufferIndex 213 ); 214 215 /** 216 Returns from the EBC stack by stack Index. 217 218 @param Index Specifies which EBC stack to return from. 219 220 @retval EFI_SUCCESS The function completed successfully. 221 222 **/ 223 EFI_STATUS 224 ReturnEBCStack( 225 IN UINTN Index 226 ); 227 228 /** 229 Allocates memory to hold all the EBC stacks. 230 231 @retval EFI_SUCCESS The EBC stacks were allocated successfully. 232 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks. 233 234 **/ 235 EFI_STATUS 236 InitEBCStack ( 237 VOID 238 ); 239 240 /** 241 Free all EBC stacks allocated before. 242 243 @retval EFI_SUCCESS All the EBC stacks were freed. 244 245 **/ 246 EFI_STATUS 247 FreeEBCStack( 248 VOID 249 ); 250 251 /** 252 Returns from the EBC stack associated with the Handle parameter. 253 254 @param Handle Specifies the EFI handle to find the EBC stack with. 255 256 @retval EFI_SUCCESS The function completed successfully. 257 258 **/ 259 EFI_STATUS 260 ReturnEBCStackByHandle( 261 IN EFI_HANDLE Handle 262 ); 263 264 typedef struct { 265 EFI_EBC_PROTOCOL *This; 266 VOID *EntryPoint; 267 EFI_HANDLE ImageHandle; 268 VM_CONTEXT VmContext; 269 } EFI_EBC_THUNK_DATA; 270 271 #define EBC_PROTOCOL_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('e', 'b', 'c', 'p') 272 273 274 #define EBC_PROTOCOL_PRIVATE_DATA_FROM_THIS(a) \ 275 CR(a, EBC_PROTOCOL_PRIVATE_DATA, EbcProtocol, EBC_PROTOCOL_PRIVATE_DATA_SIGNATURE) 276 277 278 #endif // #ifndef _EBC_INT_H_ 279