TianoCore EDK2 master
Loading...
Searching...
No Matches
CcInstruction.c
Go to the documentation of this file.
1
9#include <Base.h>
10#include <Uefi.h>
14#include "CcInstruction.h"
15
16#define MAX_INSTRUCTION_LENGTH 15
17
30UINT64 *
33 IN UINT8 Register
34 )
35{
36 UINT64 *Reg;
37
38 switch (Register) {
39 case 0:
40 Reg = &Regs->Rax;
41 break;
42 case 1:
43 Reg = &Regs->Rcx;
44 break;
45 case 2:
46 Reg = &Regs->Rdx;
47 break;
48 case 3:
49 Reg = &Regs->Rbx;
50 break;
51 case 4:
52 Reg = &Regs->Rsp;
53 break;
54 case 5:
55 Reg = &Regs->Rbp;
56 break;
57 case 6:
58 Reg = &Regs->Rsi;
59 break;
60 case 7:
61 Reg = &Regs->Rdi;
62 break;
63 case 8:
64 Reg = &Regs->R8;
65 break;
66 case 9:
67 Reg = &Regs->R9;
68 break;
69 case 10:
70 Reg = &Regs->R10;
71 break;
72 case 11:
73 Reg = &Regs->R11;
74 break;
75 case 12:
76 Reg = &Regs->R12;
77 break;
78 case 13:
79 Reg = &Regs->R13;
80 break;
81 case 14:
82 Reg = &Regs->R14;
83 break;
84 case 15:
85 Reg = &Regs->R15;
86 break;
87 default:
88 Reg = NULL;
89 }
90
91 ASSERT (Reg != NULL);
92
93 return Reg;
94}
95
103STATIC
104VOID
106 IN OUT CC_INSTRUCTION_DATA *InstructionData,
107 IN UINTN Size
108 )
109{
110 InstructionData->DisplacementSize = Size;
111 InstructionData->Immediate += Size;
112 InstructionData->End += Size;
113}
114
127STATIC
128BOOLEAN
130 IN CC_INSTRUCTION_DATA *InstructionData
131 )
132{
134
135 Ext = &InstructionData->Ext;
136
137 return ((InstructionData->Mode == LongMode64Bit) &&
138 (Ext->ModRm.Mod == 0) &&
139 (Ext->ModRm.Rm == 5) &&
140 (InstructionData->SibPresent == FALSE));
141}
142
155STATIC
156UINT64
159 IN CC_INSTRUCTION_DATA *InstructionData
160 )
161{
163 UINT64 EffectiveAddress;
164
165 Ext = &InstructionData->Ext;
166 EffectiveAddress = 0;
167
168 if (IsRipRelative (InstructionData)) {
169 //
170 // RIP-relative displacement is a 32-bit signed value
171 //
172 INT32 RipRelative;
173
174 RipRelative = *(INT32 *)InstructionData->Displacement;
175
176 UpdateForDisplacement (InstructionData, 4);
177
178 //
179 // Negative displacement is handled by standard UINT64 wrap-around.
180 //
181 return Regs->Rip + (UINT64)RipRelative;
182 }
183
184 switch (Ext->ModRm.Mod) {
185 case 1:
186 UpdateForDisplacement (InstructionData, 1);
187 EffectiveAddress += (UINT64)(*(INT8 *)(InstructionData->Displacement));
188 break;
189 case 2:
190 switch (InstructionData->AddrSize) {
191 case Size16Bits:
192 UpdateForDisplacement (InstructionData, 2);
193 EffectiveAddress += (UINT64)(*(INT16 *)(InstructionData->Displacement));
194 break;
195 default:
196 UpdateForDisplacement (InstructionData, 4);
197 EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));
198 break;
199 }
200
201 break;
202 }
203
204 if (InstructionData->SibPresent) {
205 INT64 Displacement;
206
207 if (Ext->Sib.Index != 4) {
208 CopyMem (
209 &Displacement,
210 CcGetRegisterPointer (Regs, Ext->Sib.Index),
211 sizeof (Displacement)
212 );
213 Displacement *= (INT64)(1 << Ext->Sib.Scale);
214
215 //
216 // Negative displacement is handled by standard UINT64 wrap-around.
217 //
218 EffectiveAddress += (UINT64)Displacement;
219 }
220
221 if ((Ext->Sib.Base != 5) || Ext->ModRm.Mod) {
222 EffectiveAddress += *CcGetRegisterPointer (Regs, Ext->Sib.Base);
223 } else {
224 UpdateForDisplacement (InstructionData, 4);
225 EffectiveAddress += (UINT64)(*(INT32 *)(InstructionData->Displacement));
226 }
227 } else {
228 EffectiveAddress += *CcGetRegisterPointer (Regs, Ext->ModRm.Rm);
229 }
230
231 return EffectiveAddress;
232}
233
244VOID
247 IN OUT CC_INSTRUCTION_DATA *InstructionData
248 )
249{
251 INSTRUCTION_REX_PREFIX *RexPrefix;
252 INSTRUCTION_MODRM *ModRm;
253 INSTRUCTION_SIB *Sib;
254
255 RexPrefix = &InstructionData->RexPrefix;
256 Ext = &InstructionData->Ext;
257 ModRm = &InstructionData->ModRm;
258 Sib = &InstructionData->Sib;
259
260 InstructionData->ModRmPresent = TRUE;
261 ModRm->Uint8 = *(InstructionData->End);
262
263 InstructionData->Displacement++;
264 InstructionData->Immediate++;
265 InstructionData->End++;
266
267 Ext->ModRm.Mod = ModRm->Bits.Mod;
268 Ext->ModRm.Reg = (RexPrefix->Bits.BitR << 3) | ModRm->Bits.Reg;
269 Ext->ModRm.Rm = (RexPrefix->Bits.BitB << 3) | ModRm->Bits.Rm;
270
271 Ext->RegData = *CcGetRegisterPointer (Regs, Ext->ModRm.Reg);
272
273 if (Ext->ModRm.Mod == 3) {
274 Ext->RmData = *CcGetRegisterPointer (Regs, Ext->ModRm.Rm);
275 } else {
276 if (ModRm->Bits.Rm == 4) {
277 InstructionData->SibPresent = TRUE;
278 Sib->Uint8 = *(InstructionData->End);
279
280 InstructionData->Displacement++;
281 InstructionData->Immediate++;
282 InstructionData->End++;
283
284 Ext->Sib.Scale = Sib->Bits.Scale;
285 Ext->Sib.Index = (RexPrefix->Bits.BitX << 3) | Sib->Bits.Index;
286 Ext->Sib.Base = (RexPrefix->Bits.BitB << 3) | Sib->Bits.Base;
287 }
288
289 Ext->RmData = GetEffectiveMemoryAddress (Regs, InstructionData);
290 }
291}
292
305STATIC
309 IN OUT CC_INSTRUCTION_DATA *InstructionData
310 )
311{
312 CC_INSTRUCTION_MODE Mode;
313 CC_INSTRUCTION_SIZE ModeDataSize;
314 CC_INSTRUCTION_SIZE ModeAddrSize;
315 UINT8 *Byte;
316 UINT8 ParsedLength;
317
318 ParsedLength = 0;
319
320 //
321 // Always in 64-bit mode
322 //
323 Mode = LongMode64Bit;
324 ModeDataSize = Size32Bits;
325 ModeAddrSize = Size64Bits;
326
327 InstructionData->Mode = Mode;
328 InstructionData->DataSize = ModeDataSize;
329 InstructionData->AddrSize = ModeAddrSize;
330
331 InstructionData->Prefixes = InstructionData->Begin;
332
333 Byte = InstructionData->Prefixes;
334 for ( ; ParsedLength <= MAX_INSTRUCTION_LENGTH; Byte++, InstructionData->PrefixSize++, ParsedLength++) {
335 //
336 // Check the 0x40 to 0x4F range using an if statement here since some
337 // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids
338 // 16 case statements below.
339 //
340 if ((*Byte >= REX_PREFIX_START) && (*Byte <= REX_PREFIX_STOP)) {
341 InstructionData->RexPrefix.Uint8 = *Byte;
342 if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) != 0) {
343 InstructionData->DataSize = Size64Bits;
344 }
345
346 continue;
347 }
348
349 switch (*Byte) {
350 case OVERRIDE_SEGMENT_CS:
351 case OVERRIDE_SEGMENT_DS:
352 case OVERRIDE_SEGMENT_ES:
353 case OVERRIDE_SEGMENT_SS:
354 if (Mode != LongMode64Bit) {
355 InstructionData->SegmentSpecified = TRUE;
356 InstructionData->Segment = (*Byte >> 3) & 3;
357 }
358
359 break;
360
361 case OVERRIDE_SEGMENT_FS:
362 case OVERRIDE_SEGMENT_GS:
363 InstructionData->SegmentSpecified = TRUE;
364 InstructionData->Segment = *Byte & 7;
365 break;
366
367 case OVERRIDE_OPERAND_SIZE:
368 if (InstructionData->RexPrefix.Uint8 == 0) {
369 InstructionData->DataSize =
370 (Mode == LongMode64Bit) ? Size16Bits :
371 (Mode == LongModeCompat32Bit) ? Size16Bits :
372 (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
373 }
374
375 break;
376
377 case OVERRIDE_ADDRESS_SIZE:
378 InstructionData->AddrSize =
379 (Mode == LongMode64Bit) ? Size32Bits :
380 (Mode == LongModeCompat32Bit) ? Size16Bits :
381 (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
382 break;
383
384 case LOCK_PREFIX:
385 break;
386
387 case REPZ_PREFIX:
388 InstructionData->RepMode = RepZ;
389 break;
390
391 case REPNZ_PREFIX:
392 InstructionData->RepMode = RepNZ;
393 break;
394
395 default:
396 InstructionData->OpCodes = Byte;
397 InstructionData->OpCodeSize = (*Byte == TWO_BYTE_OPCODE_ESCAPE) ? 2 : 1;
398
399 InstructionData->End = Byte + InstructionData->OpCodeSize;
400 InstructionData->Displacement = InstructionData->End;
401 InstructionData->Immediate = InstructionData->End;
402 return EFI_SUCCESS;
403 }
404 }
405
406 return EFI_ABORTED;
407}
408
419UINT64
421 IN CC_INSTRUCTION_DATA *InstructionData
422 )
423{
424 return (UINT64)(InstructionData->End - InstructionData->Begin);
425}
426
443 IN OUT CC_INSTRUCTION_DATA *InstructionData,
444 IN GHCB *Ghcb,
446 )
447{
448 SetMem (InstructionData, sizeof (*InstructionData), 0);
449 InstructionData->Ghcb = Ghcb;
450 InstructionData->Begin = (UINT8 *)Regs->Rip;
451 InstructionData->End = (UINT8 *)Regs->Rip;
452
453 return DecodePrefixes (Regs, InstructionData);
454}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
UINT64 * CcGetRegisterPointer(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN UINT8 Register)
Definition: CcInstruction.c:31
STATIC BOOLEAN IsRipRelative(IN CC_INSTRUCTION_DATA *InstructionData)
VOID CcDecodeModRm(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData)
STATIC VOID UpdateForDisplacement(IN OUT CC_INSTRUCTION_DATA *InstructionData, IN UINTN Size)
EFI_STATUS CcInitInstructionData(IN OUT CC_INSTRUCTION_DATA *InstructionData, IN GHCB *Ghcb, IN EFI_SYSTEM_CONTEXT_X64 *Regs)
UINT64 CcInstructionLength(IN CC_INSTRUCTION_DATA *InstructionData)
STATIC EFI_STATUS DecodePrefixes(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN OUT CC_INSTRUCTION_DATA *InstructionData)
STATIC UINT64 GetEffectiveMemoryAddress(IN EFI_SYSTEM_CONTEXT_X64 *Regs, IN CC_INSTRUCTION_DATA *InstructionData)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI Register(IN EFI_PEI_RSC_HANDLER_CALLBACK Callback)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112