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