TianoCore EDK2 master
Loading...
Searching...
No Matches
Processor.c
Go to the documentation of this file.
1
10#include <GdbStubInternal.h>
12#include <Library/PrintLib.h>
13
14//
15// Array of exception types that need to be hooked by the debugger
16// (efi, gdb) //efi number
17//
18EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
19 { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP }
20 // { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },
21 // { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP },
22 // { EXCEPT_ARM_DATA_ABORT, GDB_SIGEMT },
23 // { EXCEPT_ARM_RESERVED, GDB_SIGILL }
24};
25
26UINTN gRegisterOffsets[] = {
43 0x00000F01, // f0
44 0x00000F02,
45 0x00000F03,
46 0x00000F11, // f1
47 0x00000F12,
48 0x00000F13,
49 0x00000F21, // f2
50 0x00000F22,
51 0x00000F23,
52 0x00000F31, // f3
53 0x00000F32,
54 0x00000F33,
55 0x00000F41, // f4
56 0x00000F42,
57 0x00000F43,
58 0x00000F51, // f5
59 0x00000F52,
60 0x00000F53,
61 0x00000F61, // f6
62 0x00000F62,
63 0x00000F63,
64 0x00000F71, // f7
65 0x00000F72,
66 0x00000F73,
67 0x00000FFF, // fps
69};
70
78 VOID
79 )
80{
81 return sizeof (gExceptionType) / sizeof (EFI_EXCEPTION_TYPE_ENTRY);
82}
83
91 VOID
92 )
93{
94 return sizeof (gRegisterOffsets) / sizeof (UINTN);
95}
96
104BOOLEAN
107 )
108{
109 if (Isa == IsaArm) {
110 return TRUE;
111 } else {
112 return FALSE;
113 }
114}
115
123UINTN *
125 IN EFI_SYSTEM_CONTEXT SystemContext,
126 IN UINTN RegNumber
127 )
128{
129 UINT8 *TempPtr;
130
131 ASSERT (gRegisterOffsets[RegNumber] < 0xF00);
132 TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];
133 return (UINT32 *)TempPtr;
134}
135
143CHAR8 *
145 IN EFI_SYSTEM_CONTEXT SystemContext,
146 IN UINTN RegNumber,
147 IN CHAR8 *OutBufPtr
148 )
149{
150 UINTN RegSize;
151 CHAR8 Char;
152
153 if (gRegisterOffsets[RegNumber] > 0xF00) {
154 AsciiSPrint (OutBufPtr, 9, "00000000");
155 OutBufPtr += 8;
156 return OutBufPtr;
157 }
158
159 RegSize = 0;
160 while (RegSize < 32) {
161 Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
162 if ((Char >= 'A') && (Char <= 'F')) {
163 Char = Char - 'A' + 'a';
164 }
165
166 *OutBufPtr++ = Char;
167
168 Char = mHexToStr[(UINT8)((*FindPointerToRegister (SystemContext, RegNumber) >> RegSize) & 0xf)];
169 if ((Char >= 'A') && (Char <= 'F')) {
170 Char = Char - 'A' + 'a';
171 }
172
173 *OutBufPtr++ = Char;
174
175 RegSize = RegSize + 8;
176 }
177
178 return OutBufPtr;
179}
180
186VOID
188 IN EFI_SYSTEM_CONTEXT SystemContext,
189 IN CHAR8 *InBuffer
190 )
191{
192 UINTN RegNumber;
193 CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
194 CHAR8 *OutBufPtr; // pointer to the output buffer
195
196 RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
197
198 if (RegNumber >= MaxRegisterCount ()) {
199 SendError (GDB_EINVALIDREGNUM);
200 return;
201 }
202
203 OutBufPtr = OutBuffer;
204 OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
205
206 *OutBufPtr = '\0'; // the end of the buffer
207 SendPacket (OutBuffer);
208}
209
214VOID
215EFIAPI
217 IN EFI_SYSTEM_CONTEXT SystemContext
218 )
219{
220 UINTN Index;
221 CHAR8 *OutBuffer;
222 CHAR8 *OutBufPtr;
223 UINTN RegisterCount = MaxRegisterCount ();
224
225 // It is not safe to allocate pool here....
226 OutBuffer = AllocatePool ((RegisterCount * 8) + 1); // 8 bytes per register in string format plus a null to terminate
227 OutBufPtr = OutBuffer;
228 for (Index = 0; Index < RegisterCount; Index++) {
229 OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);
230 }
231
232 *OutBufPtr = '\0';
233 SendPacket (OutBuffer);
234 FreePool (OutBuffer);
235}
236
244CHAR8
245*
247 IN EFI_SYSTEM_CONTEXT SystemContext,
248 IN UINTN RegNumber,
249 IN CHAR8 *InBufPtr
250 )
251{
252 UINTN RegSize;
253 UINTN TempValue; // the value transferred from a hex char
254 UINT32 NewValue; // the new value of the RegNumber-th Register
255
256 if (gRegisterOffsets[RegNumber] > 0xF00) {
257 return InBufPtr + 8;
258 }
259
260 NewValue = 0;
261 RegSize = 0;
262 while (RegSize < 32) {
263 TempValue = HexCharToInt (*InBufPtr++);
264
265 if ((INTN)TempValue < 0) {
266 SendError (GDB_EBADMEMDATA);
267 return NULL;
268 }
269
270 NewValue += (TempValue << (RegSize+4));
271 TempValue = HexCharToInt (*InBufPtr++);
272
273 if ((INTN)TempValue < 0) {
274 SendError (GDB_EBADMEMDATA);
275 return NULL;
276 }
277
278 NewValue += (TempValue << RegSize);
279 RegSize = RegSize + 8;
280 }
281
282 *(FindPointerToRegister (SystemContext, RegNumber)) = NewValue;
283 return InBufPtr;
284}
285
291VOID
293 IN EFI_SYSTEM_CONTEXT SystemContext,
294 IN CHAR8 *InBuffer
295 )
296{
297 UINTN RegNumber;
298 CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
299 CHAR8 *RegNumBufPtr;
300 CHAR8 *InBufPtr; // pointer to the input buffer
301
302 // find the register number to write
303 InBufPtr = &InBuffer[1];
304 RegNumBufPtr = RegNumBuffer;
305 while (*InBufPtr != '=') {
306 *RegNumBufPtr++ = *InBufPtr++;
307 }
308
309 *RegNumBufPtr = '\0';
310 RegNumber = AsciiStrHexToUintn (RegNumBuffer);
311
312 // check if this is a valid Register Number
313 if (RegNumber >= MaxRegisterCount ()) {
314 SendError (GDB_EINVALIDREGNUM);
315 return;
316 }
317
318 InBufPtr++; // skips the '=' character
319 BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
320 SendSuccess ();
321}
322
328VOID
329EFIAPI
331 IN EFI_SYSTEM_CONTEXT SystemContext,
332 IN CHAR8 *InBuffer
333 )
334{
335 UINTN i;
336 CHAR8 *InBufPtr;
337 UINTN MinLength;
338 UINTN RegisterCount = MaxRegisterCount ();
339
340 MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format
341
342 if (AsciiStrLen (InBuffer) < MinLength) {
343 // Bad message. Message is not the right length
344 SendError (GDB_EBADBUFSIZE);
345 return;
346 }
347
348 InBufPtr = &InBuffer[1];
349
350 // Read the new values for the registers from the input buffer to an array, NewValueArray.
351 // The values in the array are in the gdb ordering
352 for (i = 0; i < RegisterCount; i++) {
353 InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
354 }
355
356 SendSuccess ();
357}
358
359// What about Thumb?
360// Use SWI 0xdbdbdb as the debug instruction
361#define GDB_ARM_BKPT 0xefdbdbdb
362
363BOOLEAN mSingleStepActive = FALSE;
364UINT32 mSingleStepPC;
365UINT32 mSingleStepData;
366UINTN mSingleStepDataSize;
367
368typedef struct {
369 LIST_ENTRY Link;
370 UINT64 Signature;
371 UINT32 Address;
372 UINT32 Instruction;
374
375#define ARM_SOFTWARE_BREAKPOINT_SIGNATURE SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T')
376#define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a) CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE)
377
378LIST_ENTRY BreakpointList;
379
385VOID
387 IN EFI_SYSTEM_CONTEXT SystemContext
388 )
389{
390 if (mSingleStepActive) {
391 // Currently don't support nesting
392 return;
393 }
394
395 mSingleStepActive = TRUE;
396
397 mSingleStepPC = SystemContext.SystemContextArm->PC;
398
399 mSingleStepDataSize = sizeof (UINT32);
400 mSingleStepData = (*(UINT32 *)mSingleStepPC);
401 *(UINT32 *)mSingleStepPC = GDB_ARM_BKPT;
402 if (*(UINT32 *)mSingleStepPC != GDB_ARM_BKPT) {
403 // For some reason our breakpoint did not take
404 mSingleStepActive = FALSE;
405 }
406
407 InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize);
408 // DEBUG((DEBUG_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC));
409}
410
416VOID
418 IN EFI_SYSTEM_CONTEXT SystemContext
419 )
420{
421 if (!mSingleStepActive) {
422 return;
423 }
424
425 if (mSingleStepDataSize == sizeof (UINT16)) {
426 *(UINT16 *)mSingleStepPC = (UINT16)mSingleStepData;
427 } else {
428 // DEBUG((DEBUG_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData));
429 *(UINT32 *)mSingleStepPC = mSingleStepData;
430 }
431
432 InvalidateInstructionCacheRange ((VOID *)mSingleStepPC, mSingleStepDataSize);
433 mSingleStepActive = FALSE;
434}
435
442VOID
443EFIAPI
445 IN EFI_SYSTEM_CONTEXT SystemContext,
446 IN CHAR8 *PacketData
447 )
448{
449 if (PacketData[1] != '\0') {
450 SystemContext.SystemContextArm->PC = AsciiStrHexToUintn (&PacketData[1]);
451 }
452}
453
460VOID
461EFIAPI
463 IN EFI_SYSTEM_CONTEXT SystemContext,
464 IN CHAR8 *PacketData
465 )
466{
468}
469
470UINTN
471GetBreakpointDataAddress (
472 IN EFI_SYSTEM_CONTEXT SystemContext,
473 IN UINTN BreakpointNumber
474 )
475{
476 return 0;
477}
478
479UINTN
480GetBreakpointDetected (
481 IN EFI_SYSTEM_CONTEXT SystemContext
482 )
483{
484 return 0;
485}
486
487BREAK_TYPE
488GetBreakpointType (
489 IN EFI_SYSTEM_CONTEXT SystemContext,
490 IN UINTN BreakpointNumber
491 )
492{
493 return NotSupported;
494}
495
497SearchBreakpointList (
498 IN UINT32 Address
499 )
500{
501 LIST_ENTRY *Current;
502 ARM_SOFTWARE_BREAKPOINT *Breakpoint;
503
504 Current = GetFirstNode (&BreakpointList);
505 while (!IsNull (&BreakpointList, Current)) {
506 Breakpoint = ARM_SOFTWARE_BREAKPOINT_FROM_LINK (Current);
507
508 if (Address == Breakpoint->Address) {
509 return Breakpoint;
510 }
511
512 Current = GetNextNode (&BreakpointList, Current);
513 }
514
515 return NULL;
516}
517
518VOID
519SetBreakpoint (
520 IN UINT32 Address
521 )
522{
523 ARM_SOFTWARE_BREAKPOINT *Breakpoint;
524
525 Breakpoint = SearchBreakpointList (Address);
526
527 if (Breakpoint != NULL) {
528 return;
529 }
530
531 // create and fill breakpoint structure
532 Breakpoint = AllocatePool (sizeof (ARM_SOFTWARE_BREAKPOINT));
533
534 Breakpoint->Signature = ARM_SOFTWARE_BREAKPOINT_SIGNATURE;
535 Breakpoint->Address = Address;
536 Breakpoint->Instruction = *(UINT32 *)Address;
537
538 // Add it to the list
539 InsertTailList (&BreakpointList, &Breakpoint->Link);
540
541 // Insert the software breakpoint
542 *(UINT32 *)Address = GDB_ARM_BKPT;
543 InvalidateInstructionCacheRange ((VOID *)Address, 4);
544
545 // DEBUG((DEBUG_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address));
546}
547
548VOID
549ClearBreakpoint (
550 IN UINT32 Address
551 )
552{
553 ARM_SOFTWARE_BREAKPOINT *Breakpoint;
554
555 Breakpoint = SearchBreakpointList (Address);
556
557 if (Breakpoint == NULL) {
558 return;
559 }
560
561 // Add it to the list
562 RemoveEntryList (&Breakpoint->Link);
563
564 // Restore the original instruction
565 *(UINT32 *)Address = Breakpoint->Instruction;
566 InvalidateInstructionCacheRange ((VOID *)Address, 4);
567
568 // DEBUG((DEBUG_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address));
569
570 FreePool (Breakpoint);
571}
572
573VOID
574EFIAPI
576 IN EFI_SYSTEM_CONTEXT SystemContext,
577 IN CHAR8 *PacketData
578 )
579{
580 UINTN Type;
581 UINTN Address;
582 UINTN Length;
583 UINTN ErrorCode;
584
585 ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
586 if (ErrorCode > 0) {
587 SendError ((UINT8)ErrorCode);
588 return;
589 }
590
591 switch (Type) {
592 case 0: // Software breakpoint
593 break;
594
595 default:
596 DEBUG ((DEBUG_ERROR, "Insert breakpoint default: %x\n", Type));
597 SendError (GDB_EINVALIDBRKPOINTTYPE);
598 return;
599 }
600
601 SetBreakpoint (Address);
602
603 SendSuccess ();
604}
605
606VOID
607EFIAPI
609 IN EFI_SYSTEM_CONTEXT SystemContext,
610 IN CHAR8 *PacketData
611 )
612{
613 UINTN Type;
614 UINTN Address;
615 UINTN Length;
616 UINTN ErrorCode;
617
618 // Parse breakpoint packet data
619 ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
620 if (ErrorCode > 0) {
621 SendError ((UINT8)ErrorCode);
622 return;
623 }
624
625 switch (Type) {
626 case 0: // Software breakpoint
627 break;
628
629 default:
630 SendError (GDB_EINVALIDBRKPOINTTYPE);
631 return;
632 }
633
634 ClearBreakpoint (Address);
635
636 SendSuccess ();
637}
638
639VOID
640InitializeProcessor (
641 VOID
642 )
643{
644 // Initialize breakpoint list
645 InitializeListHead (&BreakpointList);
646}
647
648BOOLEAN
649ValidateAddress (
650 IN VOID *Address
651 )
652{
653 if ((UINT32)Address < 0x80000000) {
654 return FALSE;
655 } else {
656 return TRUE;
657 }
658}
659
660BOOLEAN
661ValidateException (
662 IN EFI_EXCEPTION_TYPE ExceptionType,
663 IN OUT EFI_SYSTEM_CONTEXT SystemContext
664 )
665{
666 UINT32 ExceptionAddress;
667 UINT32 Instruction;
668
669 // Is it a debugger SWI?
670 ExceptionAddress = SystemContext.SystemContextArm->PC -= 4;
671 Instruction = *(UINT32 *)ExceptionAddress;
672 if (Instruction != GDB_ARM_BKPT) {
673 return FALSE;
674 }
675
676 // Special for SWI-based exception handling. SWI sets up the context
677 // to return to the instruction following the SWI instruction - NOT what we want
678 // for a debugger!
679 SystemContext.SystemContextArm->PC = ExceptionAddress;
680
681 return TRUE;
682}
UINT64 UINTN
INT64 INTN
UINTN MaxEfiException(VOID)
Definition: Processor.c:77
VOID EFIAPI RemoveBreakPoint(IN EFI_SYSTEM_CONTEXT SystemContext, IN CHAR8 *PacketData)
Definition: Processor.c:608
UINTN MaxRegisterCount(VOID)
Definition: Processor.c:90
VOID EFIAPI WriteGeneralRegisters(IN EFI_SYSTEM_CONTEXT SystemContext, IN CHAR8 *InBuffer)
Definition: Processor.c:330
CHAR8 * BasicReadRegister(IN EFI_SYSTEM_CONTEXT SystemContext, IN UINTN RegNumber, IN CHAR8 *OutBufPtr)
Definition: Processor.c:144
VOID EFIAPI InsertBreakPoint(IN EFI_SYSTEM_CONTEXT SystemContext, IN CHAR8 *PacketData)
Definition: Processor.c:575
VOID ReadNthRegister(IN EFI_SYSTEM_CONTEXT SystemContext, IN CHAR8 *InBuffer)
Definition: Processor.c:187
CHAR8 * BasicWriteRegister(IN EFI_SYSTEM_CONTEXT SystemContext, IN UINTN RegNumber, IN CHAR8 *InBufPtr)
Definition: Processor.c:246
BOOLEAN CheckIsa(IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa)
Definition: Processor.c:105
VOID EFIAPI ReadGeneralRegisters(IN EFI_SYSTEM_CONTEXT SystemContext)
Definition: Processor.c:216
VOID RemoveSingleStep(IN EFI_SYSTEM_CONTEXT SystemContext)
Definition: Processor.c:417
VOID AddSingleStep(IN EFI_SYSTEM_CONTEXT SystemContext)
Definition: Processor.c:386
VOID EFIAPI SingleStep(IN EFI_SYSTEM_CONTEXT SystemContext, IN CHAR8 *PacketData)
Definition: Processor.c:462
VOID WriteNthRegister(IN EFI_SYSTEM_CONTEXT SystemContext, IN CHAR8 *InBuffer)
Definition: Processor.c:292
UINTN * FindPointerToRegister(IN EFI_SYSTEM_CONTEXT SystemContext, IN UINTN RegNumber)
Definition: Processor.c:124
VOID EFIAPI ContinueAtAddress(IN EFI_SYSTEM_CONTEXT SystemContext, IN CHAR8 *PacketData)
Definition: Processor.c:444
VOID *EFIAPI InvalidateInstructionCacheRange(IN VOID *Address, IN UINTN Length)
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
UINTN EFIAPI AsciiStrHexToUintn(IN CONST CHAR8 *String)
Definition: String.c:1104
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID EFIAPI FreePool(IN VOID *Buffer)
UINTN ParseBreakpointPacket(IN CHAR8 *PacketData, OUT UINTN *Type, OUT UINTN *Address, OUT UINTN *Length)
Definition: GdbStub.c:719
VOID EFIAPI SendNotSupported(VOID)
Definition: GdbStub.c:466
UINTN SendPacket(IN CHAR8 *PacketData)
Definition: GdbStub.c:270
VOID EFIAPI SendSuccess(VOID)
Definition: GdbStub.c:454
INTN HexCharToInt(IN CHAR8 Char)
Definition: GdbStub.c:408
VOID EFIAPI SendError(IN UINT8 ErrorNum)
Definition: GdbStub.c:436
UINTN EFIAPI AsciiSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString,...)
Definition: PrintLib.c:813
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
INTN EFI_EXCEPTION_TYPE
Definition: DebugSupport.h:35
EFI_INSTRUCTION_SET_ARCHITECTURE
Definition: DebugSupport.h:836
@ IsaArm
0x01c2
Definition: DebugSupport.h:841
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)