1 | /** @file
|
---|
2 | Header file for Virtual Machine support. Contains EBC defines that can
|
---|
3 | be of use to a disassembler for the most part. Also provides function
|
---|
4 | prototypes for VM functions.
|
---|
5 |
|
---|
6 | Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
---|
7 | This program and the accompanying materials
|
---|
8 | are licensed and made available under the terms and conditions of the BSD License
|
---|
9 | which accompanies this distribution. The full text of the license may be found at
|
---|
10 | http://opensource.org/licenses/bsd-license.php
|
---|
11 |
|
---|
12 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
---|
13 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
---|
14 |
|
---|
15 | **/
|
---|
16 |
|
---|
17 | #ifndef _EBC_EXECUTE_H_
|
---|
18 | #define _EBC_EXECUTE_H_
|
---|
19 |
|
---|
20 | //
|
---|
21 | // VM major/minor version
|
---|
22 | //
|
---|
23 | #define VM_MAJOR_VERSION 1
|
---|
24 | #define VM_MINOR_VERSION 0
|
---|
25 |
|
---|
26 | //
|
---|
27 | // Macros to check and set alignment
|
---|
28 | //
|
---|
29 | #define ASSERT_ALIGNED(addr, size) ASSERT (!((UINT32) (addr) & (size - 1)))
|
---|
30 | #define IS_ALIGNED(addr, size) !((UINT32) (addr) & (size - 1))
|
---|
31 |
|
---|
32 | //
|
---|
33 | // Define a macro to get the operand. Then we can change it to be either a
|
---|
34 | // direct read or have it call a function to read memory.
|
---|
35 | //
|
---|
36 | #define GETOPERANDS(pVM) (UINT8) (*(UINT8 *) (pVM->Ip + 1))
|
---|
37 | #define GETOPCODE(pVM) (UINT8) (*(UINT8 *) pVM->Ip)
|
---|
38 |
|
---|
39 | //
|
---|
40 | // Bit masks for opcode encodings
|
---|
41 | //
|
---|
42 | #define OPCODE_M_OPCODE 0x3F // bits of interest for first level decode
|
---|
43 | #define OPCODE_M_IMMDATA 0x80
|
---|
44 | #define OPCODE_M_IMMDATA64 0x40
|
---|
45 | #define OPCODE_M_64BIT 0x40 // for CMP
|
---|
46 | #define OPCODE_M_RELADDR 0x10 // for CALL instruction
|
---|
47 | #define OPCODE_M_CMPI32_DATA 0x80 // for CMPI
|
---|
48 | #define OPCODE_M_CMPI64 0x40 // for CMPI 32 or 64 bit comparison
|
---|
49 | #define OPERAND_M_MOVIN_N 0x80
|
---|
50 | #define OPERAND_M_CMPI_INDEX 0x10
|
---|
51 |
|
---|
52 | //
|
---|
53 | // Masks for instructions that encode presence of indexes for operand1 and/or
|
---|
54 | // operand2.
|
---|
55 | //
|
---|
56 | #define OPCODE_M_IMMED_OP1 0x80
|
---|
57 | #define OPCODE_M_IMMED_OP2 0x40
|
---|
58 |
|
---|
59 | //
|
---|
60 | // Bit masks for operand encodings
|
---|
61 | //
|
---|
62 | #define OPERAND_M_INDIRECT1 0x08
|
---|
63 | #define OPERAND_M_INDIRECT2 0x80
|
---|
64 | #define OPERAND_M_OP1 0x07
|
---|
65 | #define OPERAND_M_OP2 0x70
|
---|
66 |
|
---|
67 | //
|
---|
68 | // Masks for data manipulation instructions
|
---|
69 | //
|
---|
70 | #define DATAMANIP_M_64 0x40 // 64-bit width operation
|
---|
71 | #define DATAMANIP_M_IMMDATA 0x80
|
---|
72 |
|
---|
73 | //
|
---|
74 | // For MOV instructions, need a mask for the opcode when immediate
|
---|
75 | // data applies to R2.
|
---|
76 | //
|
---|
77 | #define OPCODE_M_IMMED_OP2 0x40
|
---|
78 |
|
---|
79 | //
|
---|
80 | // The MOVI/MOVIn instructions use bit 6 of operands byte to indicate
|
---|
81 | // if an index is present. Then bits 4 and 5 are used to indicate the width
|
---|
82 | // of the move.
|
---|
83 | //
|
---|
84 | #define MOVI_M_IMMDATA 0x40
|
---|
85 | #define MOVI_M_DATAWIDTH 0xC0
|
---|
86 | #define MOVI_DATAWIDTH16 0x40
|
---|
87 | #define MOVI_DATAWIDTH32 0x80
|
---|
88 | #define MOVI_DATAWIDTH64 0xC0
|
---|
89 | #define MOVI_M_MOVEWIDTH 0x30
|
---|
90 | #define MOVI_MOVEWIDTH8 0x00
|
---|
91 | #define MOVI_MOVEWIDTH16 0x10
|
---|
92 | #define MOVI_MOVEWIDTH32 0x20
|
---|
93 | #define MOVI_MOVEWIDTH64 0x30
|
---|
94 |
|
---|
95 | //
|
---|
96 | // Masks for CALL instruction encodings
|
---|
97 | //
|
---|
98 | #define OPERAND_M_RELATIVE_ADDR 0x10
|
---|
99 | #define OPERAND_M_NATIVE_CALL 0x20
|
---|
100 |
|
---|
101 | //
|
---|
102 | // Masks for decoding push/pop instructions
|
---|
103 | //
|
---|
104 | #define PUSHPOP_M_IMMDATA 0x80 // opcode bit indicating immediate data
|
---|
105 | #define PUSHPOP_M_64 0x40 // opcode bit indicating 64-bit operation
|
---|
106 | //
|
---|
107 | // Mask for operand of JMP instruction
|
---|
108 | //
|
---|
109 | #define JMP_M_RELATIVE 0x10
|
---|
110 | #define JMP_M_CONDITIONAL 0x80
|
---|
111 | #define JMP_M_CS 0x40
|
---|
112 |
|
---|
113 | //
|
---|
114 | // Macros to determine if a given operand is indirect
|
---|
115 | //
|
---|
116 | #define OPERAND1_INDIRECT(op) ((op) & OPERAND_M_INDIRECT1)
|
---|
117 | #define OPERAND2_INDIRECT(op) ((op) & OPERAND_M_INDIRECT2)
|
---|
118 |
|
---|
119 | //
|
---|
120 | // Macros to extract the operands from second byte of instructions
|
---|
121 | //
|
---|
122 | #define OPERAND1_REGNUM(op) ((op) & OPERAND_M_OP1)
|
---|
123 | #define OPERAND2_REGNUM(op) (((op) & OPERAND_M_OP2) >> 4)
|
---|
124 |
|
---|
125 | #define OPERAND1_CHAR(op) ('0' + OPERAND1_REGNUM (op))
|
---|
126 | #define OPERAND2_CHAR(op) ('0' + OPERAND2_REGNUM (op))
|
---|
127 |
|
---|
128 | #define OPERAND1_REGDATA(pvm, op) pvm->Gpr[OPERAND1_REGNUM (op)]
|
---|
129 | #define OPERAND2_REGDATA(pvm, op) pvm->Gpr[OPERAND2_REGNUM (op)]
|
---|
130 |
|
---|
131 | //
|
---|
132 | // Condition masks usually for byte 1 encodings of code
|
---|
133 | //
|
---|
134 | #define CONDITION_M_CONDITIONAL 0x80
|
---|
135 | #define CONDITION_M_CS 0x40
|
---|
136 |
|
---|
137 | //
|
---|
138 | // Bits in the VM->StopFlags field
|
---|
139 | //
|
---|
140 | #define STOPFLAG_APP_DONE 0x0001
|
---|
141 | #define STOPFLAG_BREAKPOINT 0x0002
|
---|
142 | #define STOPFLAG_INVALID_BREAK 0x0004
|
---|
143 | #define STOPFLAG_BREAK_ON_CALLEX 0x0008
|
---|
144 |
|
---|
145 | //
|
---|
146 | // Masks for working with the VM flags register
|
---|
147 | //
|
---|
148 | #define VMFLAGS_CC 0x0001 // condition flag
|
---|
149 | #define VMFLAGS_STEP 0x0002 // step instruction mode
|
---|
150 | #define VMFLAGS_ALL_VALID (VMFLAGS_CC | VMFLAGS_STEP)
|
---|
151 |
|
---|
152 | //
|
---|
153 | // Macros for operating on the VM flags register
|
---|
154 | //
|
---|
155 | #define VMFLAG_SET(pVM, Flag) (pVM->Flags |= (Flag))
|
---|
156 | #define VMFLAG_ISSET(pVM, Flag) ((pVM->Flags & (Flag)) ? 1 : 0)
|
---|
157 | #define VMFLAG_CLEAR(pVM, Flag) (pVM->Flags &= ~(Flag))
|
---|
158 |
|
---|
159 | //
|
---|
160 | // Debug macro
|
---|
161 | //
|
---|
162 | #define EBCMSG(s) gST->ConOut->OutputString (gST->ConOut, s)
|
---|
163 |
|
---|
164 | //
|
---|
165 | // Define OPCODES
|
---|
166 | //
|
---|
167 | #define OPCODE_BREAK 0x00
|
---|
168 | #define OPCODE_JMP 0x01
|
---|
169 | #define OPCODE_JMP8 0x02
|
---|
170 | #define OPCODE_CALL 0x03
|
---|
171 | #define OPCODE_RET 0x04
|
---|
172 | #define OPCODE_CMPEQ 0x05
|
---|
173 | #define OPCODE_CMPLTE 0x06
|
---|
174 | #define OPCODE_CMPGTE 0x07
|
---|
175 | #define OPCODE_CMPULTE 0x08
|
---|
176 | #define OPCODE_CMPUGTE 0x09
|
---|
177 | #define OPCODE_NOT 0x0A
|
---|
178 | #define OPCODE_NEG 0x0B
|
---|
179 | #define OPCODE_ADD 0x0C
|
---|
180 | #define OPCODE_SUB 0x0D
|
---|
181 | #define OPCODE_MUL 0x0E
|
---|
182 | #define OPCODE_MULU 0x0F
|
---|
183 | #define OPCODE_DIV 0x10
|
---|
184 | #define OPCODE_DIVU 0x11
|
---|
185 | #define OPCODE_MOD 0x12
|
---|
186 | #define OPCODE_MODU 0x13
|
---|
187 | #define OPCODE_AND 0x14
|
---|
188 | #define OPCODE_OR 0x15
|
---|
189 | #define OPCODE_XOR 0x16
|
---|
190 | #define OPCODE_SHL 0x17
|
---|
191 | #define OPCODE_SHR 0x18
|
---|
192 | #define OPCODE_ASHR 0x19
|
---|
193 | #define OPCODE_EXTNDB 0x1A
|
---|
194 | #define OPCODE_EXTNDW 0x1B
|
---|
195 | #define OPCODE_EXTNDD 0x1C
|
---|
196 | #define OPCODE_MOVBW 0x1D
|
---|
197 | #define OPCODE_MOVWW 0x1E
|
---|
198 | #define OPCODE_MOVDW 0x1F
|
---|
199 | #define OPCODE_MOVQW 0x20
|
---|
200 | #define OPCODE_MOVBD 0x21
|
---|
201 | #define OPCODE_MOVWD 0x22
|
---|
202 | #define OPCODE_MOVDD 0x23
|
---|
203 | #define OPCODE_MOVQD 0x24
|
---|
204 | #define OPCODE_MOVSNW 0x25 // Move signed natural with word index
|
---|
205 | #define OPCODE_MOVSND 0x26 // Move signed natural with dword index
|
---|
206 | //
|
---|
207 | // #define OPCODE_27 0x27
|
---|
208 | //
|
---|
209 | #define OPCODE_MOVQQ 0x28 // Does this go away?
|
---|
210 | #define OPCODE_LOADSP 0x29
|
---|
211 | #define OPCODE_STORESP 0x2A
|
---|
212 | #define OPCODE_PUSH 0x2B
|
---|
213 | #define OPCODE_POP 0x2C
|
---|
214 | #define OPCODE_CMPIEQ 0x2D
|
---|
215 | #define OPCODE_CMPILTE 0x2E
|
---|
216 | #define OPCODE_CMPIGTE 0x2F
|
---|
217 | #define OPCODE_CMPIULTE 0x30
|
---|
218 | #define OPCODE_CMPIUGTE 0x31
|
---|
219 | #define OPCODE_MOVNW 0x32
|
---|
220 | #define OPCODE_MOVND 0x33
|
---|
221 | //
|
---|
222 | // #define OPCODE_34 0x34
|
---|
223 | //
|
---|
224 | #define OPCODE_PUSHN 0x35
|
---|
225 | #define OPCODE_POPN 0x36
|
---|
226 | #define OPCODE_MOVI 0x37
|
---|
227 | #define OPCODE_MOVIN 0x38
|
---|
228 | #define OPCODE_MOVREL 0x39
|
---|
229 |
|
---|
230 | /**
|
---|
231 | Execute an EBC image from an entry point or from a published protocol.
|
---|
232 |
|
---|
233 | @param VmPtr A pointer to a VM context.
|
---|
234 |
|
---|
235 | @retval EFI_UNSUPPORTED At least one of the opcodes is not supported.
|
---|
236 | @retval EFI_SUCCESS All of the instructions are executed successfully.
|
---|
237 |
|
---|
238 | **/
|
---|
239 | EFI_STATUS
|
---|
240 | EbcExecute (
|
---|
241 | IN VM_CONTEXT *VmPtr
|
---|
242 | );
|
---|
243 |
|
---|
244 |
|
---|
245 |
|
---|
246 | /**
|
---|
247 | Returns the version of the EBC virtual machine.
|
---|
248 |
|
---|
249 | @return The 64-bit version of EBC virtual machine.
|
---|
250 |
|
---|
251 | **/
|
---|
252 | UINT64
|
---|
253 | GetVmVersion (
|
---|
254 | VOID
|
---|
255 | );
|
---|
256 |
|
---|
257 | /**
|
---|
258 | Writes UINTN data to memory address.
|
---|
259 |
|
---|
260 | This routine is called by the EBC data
|
---|
261 | movement instructions that write to memory. Since these writes
|
---|
262 | may be to the stack, which looks like (high address on top) this,
|
---|
263 |
|
---|
264 | [EBC entry point arguments]
|
---|
265 | [VM stack]
|
---|
266 | [EBC stack]
|
---|
267 |
|
---|
268 | we need to detect all attempts to write to the EBC entry point argument
|
---|
269 | stack area and adjust the address (which will initially point into the
|
---|
270 | VM stack) to point into the EBC entry point arguments.
|
---|
271 |
|
---|
272 | @param VmPtr A pointer to a VM context.
|
---|
273 | @param Addr Address to write to.
|
---|
274 | @param Data Value to write to Addr.
|
---|
275 |
|
---|
276 | @retval EFI_SUCCESS The instruction is executed successfully.
|
---|
277 | @retval Other Some error occurs when writing data to the address.
|
---|
278 |
|
---|
279 | **/
|
---|
280 | EFI_STATUS
|
---|
281 | VmWriteMemN (
|
---|
282 | IN VM_CONTEXT *VmPtr,
|
---|
283 | IN UINTN Addr,
|
---|
284 | IN UINTN Data
|
---|
285 | );
|
---|
286 |
|
---|
287 | /**
|
---|
288 | Writes 64-bit data to memory address.
|
---|
289 |
|
---|
290 | This routine is called by the EBC data
|
---|
291 | movement instructions that write to memory. Since these writes
|
---|
292 | may be to the stack, which looks like (high address on top) this,
|
---|
293 |
|
---|
294 | [EBC entry point arguments]
|
---|
295 | [VM stack]
|
---|
296 | [EBC stack]
|
---|
297 |
|
---|
298 | we need to detect all attempts to write to the EBC entry point argument
|
---|
299 | stack area and adjust the address (which will initially point into the
|
---|
300 | VM stack) to point into the EBC entry point arguments.
|
---|
301 |
|
---|
302 | @param VmPtr A pointer to a VM context.
|
---|
303 | @param Addr Address to write to.
|
---|
304 | @param Data Value to write to Addr.
|
---|
305 |
|
---|
306 | @retval EFI_SUCCESS The instruction is executed successfully.
|
---|
307 | @retval Other Some error occurs when writing data to the address.
|
---|
308 |
|
---|
309 | **/
|
---|
310 | EFI_STATUS
|
---|
311 | VmWriteMem64 (
|
---|
312 | IN VM_CONTEXT *VmPtr,
|
---|
313 | IN UINTN Addr,
|
---|
314 | IN UINT64 Data
|
---|
315 | );
|
---|
316 |
|
---|
317 | /**
|
---|
318 | Given a pointer to a new VM context, execute one or more instructions. This
|
---|
319 | function is only used for test purposes via the EBC VM test protocol.
|
---|
320 |
|
---|
321 | @param This A pointer to the EFI_EBC_VM_TEST_PROTOCOL structure.
|
---|
322 | @param VmPtr A pointer to a VM context.
|
---|
323 | @param InstructionCount A pointer to a UINTN value holding the number of
|
---|
324 | instructions to execute. If it holds value of 0,
|
---|
325 | then the instruction to be executed is 1.
|
---|
326 |
|
---|
327 | @retval EFI_UNSUPPORTED At least one of the opcodes is not supported.
|
---|
328 | @retval EFI_SUCCESS All of the instructions are executed successfully.
|
---|
329 |
|
---|
330 | **/
|
---|
331 | EFI_STATUS
|
---|
332 | EFIAPI
|
---|
333 | EbcExecuteInstructions (
|
---|
334 | IN EFI_EBC_VM_TEST_PROTOCOL *This,
|
---|
335 | IN VM_CONTEXT *VmPtr,
|
---|
336 | IN OUT UINTN *InstructionCount
|
---|
337 | );
|
---|
338 |
|
---|
339 | #endif // ifndef _EBC_EXECUTE_H_
|
---|