1/** @file
2  Private include file for GDB stub
3
4  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5
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 __GCC_DEBUG_AGENT_INTERNAL__
17#define __GCC_DEBUG_AGENT_INTERNAL__
18
19#include <Uefi.h>
20#include <Library/BaseLib.h>
21#include <Library/BaseMemoryLib.h>
22#include <Library/MemoryAllocationLib.h>
23#include <Library/DebugLib.h>
24#include <Library/PcdLib.h>
25#include <Library/GdbSerialLib.h>
26#include <Library/PrintLib.h>
27#include <Library/CacheMaintenanceLib.h>
28#include <Library/DebugAgentTimerLib.h>
29#include <Library/DebugAgentLib.h>
30
31#include <IndustryStandard/PeImage.h>
32#include <Protocol/DebugSupport.h>
33
34extern CONST CHAR8 mHexToStr[];
35
36// maximum size of input and output buffers
37// This value came from the show remote command of the gdb we tested against
38#define MAX_BUF_SIZE 2000
39
40// maximum size of address buffer
41#define MAX_ADDR_SIZE 32
42
43// maximum size of register number buffer
44#define MAX_REG_NUM_BUF_SIZE 32
45
46// maximum size of length buffer
47#define MAX_LENGTH_SIZE 32
48
49// maximum size of T signal members
50#define MAX_T_SIGNAL_SIZE 64
51
52// the mask used to clear all the cache
53#define TF_BIT 0x00000100
54
55
56//
57// GDB Signal definitions - generic names for interrupts
58//
59#define GDB_SIGINT      2  // Interrupt process via ctrl-c
60#define GDB_SIGILL      4  // Illegal instruction
61#define GDB_SIGTRAP     5  // Trace Trap (Breakpoint and SingleStep)
62#define GDB_SIGEMT      7  // Emulator Trap
63#define GDB_SIGFPE      8  // Floating point exception
64#define GDB_SIGSEGV     11 // Setgment violation, page fault
65
66
67//
68// GDB File I/O Error values, zero means no error
69// Includes all general GDB Unix like error values
70//
71#define GDB_EBADMEMADDRBUFSIZE   11  // the buffer that stores memory Address to be read from/written to is not the right size
72#define GDB_EBADMEMLENGBUFSIZE   12  // the buffer that stores Length is not the right size
73#define GDB_EBADMEMLENGTH        13  // Length, the given number of bytes to read or write, is not the right size
74#define GDB_EBADMEMDATA          14  // one of the bytes or nibbles of the memory is leess than 0
75#define GDB_EBADMEMDATASIZE      15  // the memory data, 'XX..', is too short or too long
76#define GDB_EBADBUFSIZE          21  // the buffer created is not the correct size
77#define GDB_EINVALIDARG          31  // argument is invalid
78#define GDB_ENOSPACE             41  //
79#define GDB_EINVALIDBRKPOINTTYPE 51  // the breakpoint type is not recognized
80#define GDB_EINVALIDREGNUM       61  // given register number is not valid: either <0 or >=Number of Registers
81#define GDB_EUNKNOWN             255 // unknown
82
83
84//
85// These devices are open by GDB so we can just read and write to them
86//
87#define GDB_STDIN   0x00
88#define GDB_STDOUT  0x01
89#define GDB_STDERR  0x02
90
91//
92//Define Register size for different architectures
93//
94#if defined (MDE_CPU_IA32)
95#define REG_SIZE  32
96#elif defined (MDE_CPU_X64)
97#define REG_SIZE  64
98#elif defined (MDE_CPU_ARM)
99#define REG_SIZE  32
100#endif
101
102
103typedef struct {
104  EFI_EXCEPTION_TYPE  Exception;
105  UINT8               SignalNo;
106} EFI_EXCEPTION_TYPE_ENTRY;
107
108
109#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
110
111//
112// Byte packed structure for DR6
113// 32-bits on IA-32
114// 64-bits on X64.  The upper 32-bits on X64 are reserved
115//
116typedef union {
117  struct {
118    UINT32  B0:1;           // Breakpoint condition detected
119    UINT32  B1:1;           // Breakpoint condition detected
120    UINT32  B2:1;           // Breakpoint condition detected
121    UINT32  B3:1;           // Breakpoint condition detected
122    UINT32  Reserved_1:9;   // Reserved
123    UINT32  BD:1;           // Debug register access detected
124    UINT32  BS:1;           // Single step
125    UINT32  BT:1;           // Task switch
126    UINT32  Reserved_2:16;  // Reserved
127  } Bits;
128  UINTN     UintN;
129} IA32_DR6;
130
131//
132// Byte packed structure for DR7
133// 32-bits on IA-32
134// 64-bits on X64.  The upper 32-bits on X64 are reserved
135//
136typedef union {
137  struct {
138    UINT32  L0:1;           // Local breakpoint enable
139    UINT32  G0:1;           // Global breakpoint enable
140    UINT32  L1:1;           // Local breakpoint enable
141    UINT32  G1:1;           // Global breakpoint enable
142    UINT32  L2:1;           // Local breakpoint enable
143    UINT32  G2:1;           // Global breakpoint enable
144    UINT32  L3:1;           // Local breakpoint enable
145    UINT32  G3:1;           // Global breakpoint enable
146    UINT32  LE:1;           // Local exact breakpoint enable
147    UINT32  GE:1;           // Global exact breakpoint enable
148    UINT32  Reserved_1:3;   // Reserved
149    UINT32  GD:1;           // Global detect enable
150    UINT32  Reserved_2:2;   // Reserved
151    UINT32  RW0:2;          // Read/Write field
152    UINT32  LEN0:2;         // Length field
153    UINT32  RW1:2;          // Read/Write field
154    UINT32  LEN1:2;         // Length field
155    UINT32  RW2:2;          // Read/Write field
156    UINT32  LEN2:2;         // Length field
157    UINT32  RW3:2;          // Read/Write field
158    UINT32  LEN3:2;         // Length field
159  } Bits;
160  UINTN     UintN;
161} IA32_DR7;
162
163#endif /* if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) */
164
165typedef enum {
166  InstructionExecution,   //Hardware breakpoint
167  DataWrite,              //watch
168  DataRead,               //rwatch
169  DataReadWrite,          //awatch
170  SoftwareBreakpoint,     //Software breakpoint
171  NotSupported
172} BREAK_TYPE;
173
174//
175// Array of exception types that need to be hooked by the debugger
176//
177extern EFI_EXCEPTION_TYPE_ENTRY gExceptionType[];
178
179//
180// If the periodic callback is called while we are processing an F packet we need
181// to let the callback know to not read from the serail stream as it could steal
182// characters from the F reponse packet
183//
184extern BOOLEAN gProcessingFPacket;
185
186
187/**
188 Return the number of entries in the gExceptionType[]
189
190 @retval    UINTN, the number of entries in the gExceptionType[] array.
191 **/
192UINTN
193MaxEfiException (
194  VOID
195  );
196
197
198/**
199 Check to see if the ISA is supported.
200 ISA = Instruction Set Architecture
201
202 @retval    TRUE if Isa is supported,
203 FALSE otherwise.
204 **/
205BOOLEAN
206CheckIsa (
207  IN    EFI_INSTRUCTION_SET_ARCHITECTURE    Isa
208  );
209
210
211/**
212 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
213
214 @param  SystemContext        Register content at time of the exception
215 @param  GdbExceptionType     GDB exception type
216 **/
217
218VOID
219GdbSendTSignal (
220  IN  EFI_SYSTEM_CONTEXT  SystemContext,
221  IN  UINT8               GdbExceptionType
222  );
223
224
225/**
226 Translates the EFI mapping to GDB mapping
227
228 @param     EFIExceptionType        EFI Exception that is being processed
229 @retval    UINTN that corresponds to EFIExceptionType's GDB exception type number
230 **/
231UINT8
232ConvertEFItoGDBtype (
233  IN  EFI_EXCEPTION_TYPE EFIExceptionType
234  );
235
236
237/**
238 Empties the given buffer
239 @param *Buf pointer to the first element in buffer to be emptied
240 **/
241VOID
242EmptyBuffer (
243  IN CHAR8  *Buf
244  );
245
246
247/**
248 Converts an 8-bit Hex Char into a INTN.
249
250 @param     Char  - the hex character to be converted into UINTN
251 @retval    a INTN, from 0 to 15, that corressponds to Char
252 -1 if Char is not a hex character
253 **/
254INTN
255HexCharToInt (
256  IN  CHAR8 Char
257  );
258
259
260/** 'E NN'
261 Send an error with the given error number after converting to hex.
262 The error number is put into the buffer in hex. '255' is the biggest errno we can send.
263 ex: 162 will be sent as A2.
264
265 @param   errno    the error number that will be sent
266 **/
267VOID
268EFIAPI
269SendError (
270  IN  UINT8     ErrorNum
271  );
272
273
274/**
275 Send 'OK' when the function is done executing successfully.
276 **/
277VOID
278SendSuccess (
279  VOID
280  );
281
282
283/**
284 Send empty packet to specify that particular command/functionality is not supported.
285 **/
286VOID
287SendNotSupported (
288  VOID
289  );
290
291/** ‘p n’
292 Reads the n-th register's value into an output buffer and sends it as a packet
293 @param     SystemContext       Register content at time of the exception
294 @param     InBuffer            This is the input buffer received from gdb server
295 **/
296VOID
297ReadNthRegister (
298  IN    EFI_SYSTEM_CONTEXT  SystemContext,
299  IN    CHAR8               *InBuffer
300  );
301
302
303/** ‘g’
304 Reads the general registers into an output buffer  and sends it as a packet
305 @param     SystemContext           Register content at time of the exception
306 **/
307VOID
308ReadGeneralRegisters (
309  IN    EFI_SYSTEM_CONTEXT  SystemContext
310  );
311
312
313/** ‘P n...=r...’
314 Writes the new value of n-th register received into the input buffer to the n-th register
315 @param     SystemContext       Register content at time of the exception
316 @param     InBuffer            This is the input buffer received from gdb server
317 **/
318VOID
319WriteNthRegister (
320  IN    EFI_SYSTEM_CONTEXT  SystemContext,
321  IN    CHAR8               *InBuffer
322  );
323
324
325/** ‘G XX...’
326 Writes the new values received into the input buffer to the general registers
327 @param     SystemContext               Register content at time of the exception
328 @param     InBuffer                    Pointer to the input buffer received from gdb server
329 **/
330
331VOID
332WriteGeneralRegisters (
333  IN    EFI_SYSTEM_CONTEXT  SystemContext,
334  IN    CHAR8               *InBuffer
335  );
336
337
338/** ‘m addr,length ’
339 Find the Length of the area to read and the start addres. Finally, pass them to
340 another function, TransferFromMemToOutBufAndSend, that will read from that memory space and
341 send it as a packet.
342
343 @param  *PacketData  Pointer to Payload data for the packet
344 **/
345VOID
346ReadFromMemory (
347  IN  CHAR8  *PacketData
348  );
349
350
351/** ‘M addr,length :XX...’
352 Find the Length of the area in bytes to write and the start addres. Finally, pass them to
353 another function, TransferFromInBufToMem, that will write to that memory space the info in
354 the input buffer.
355
356 @param   PacketData     Pointer to Payload data for the packet
357 **/
358VOID
359WriteToMemory (
360  IN CHAR8 *PacketData
361  );
362
363
364/** ‘c [addr ]’
365 Continue. addr is Address to resume. If addr is omitted, resume at current
366 Address.
367
368 @param SystemContext Register content at time of the exception
369 @param *PacketData   Pointer to PacketData
370 **/
371
372VOID
373ContinueAtAddress (
374  IN  EFI_SYSTEM_CONTEXT   SystemContext,
375  IN  CHAR8                *PacketData
376  );
377
378
379/** ‘s [addr ]’
380 Single step. addr is the Address at which to resume. If addr is omitted, resume
381 at same Address.
382
383 @param SystemContext   Register content at time of the exception
384 @param PacketData      Pointer to Payload data for the packet
385 **/
386VOID
387SingleStep (
388  IN  EFI_SYSTEM_CONTEXT  SystemContext,
389  IN  CHAR8               *PacketData
390  );
391
392/**
393 Insert Single Step in the SystemContext
394
395 @param SystemContext   Register content at time of the exception
396 **/
397VOID
398AddSingleStep (
399  IN  EFI_SYSTEM_CONTEXT  SystemContext
400  );
401
402/**
403 Remove Single Step in the SystemContext
404
405 @param SystemContext   Register content at time of the exception
406 **/
407VOID
408RemoveSingleStep (
409  IN  EFI_SYSTEM_CONTEXT  SystemContext
410  );
411
412
413/**
414  ‘Z1, [addr], [length]’
415  ‘Z2, [addr], [length]’
416  ‘Z3, [addr], [length]’
417  ‘Z4, [addr], [length]’
418
419  Insert hardware breakpoint/watchpoint at address addr of size length
420
421  @param SystemContext  Register content at time of the exception
422  @param *PacketData    Pointer to the Payload data for the packet
423
424**/
425VOID
426EFIAPI
427InsertBreakPoint(
428  IN  EFI_SYSTEM_CONTEXT  SystemContext,
429  IN  CHAR8               *PacketData
430  );
431
432
433/**
434  ‘z1, [addr], [length]’
435  ‘z2, [addr], [length]’
436  ‘z3, [addr], [length]’
437  ‘z4, [addr], [length]’
438
439  Remove hardware breakpoint/watchpoint at address addr of size length
440
441  @param SystemContext  Register content at time of the exception
442  @param *PacketData    Pointer to the Payload data for the packet
443
444**/
445VOID
446EFIAPI
447RemoveBreakPoint(
448  IN  EFI_SYSTEM_CONTEXT  SystemContext,
449  IN  CHAR8               *PacketData
450  );
451
452
453/**
454 Exception Hanldler for GDB. It will be called for all exceptions
455 registered via the gExceptionType[] array.
456
457 @param ExceptionType   Exception that is being processed
458 @param SystemContext   Register content at time of the exception
459
460 **/
461VOID
462EFIAPI
463GdbExceptionHandler (
464  IN     EFI_EXCEPTION_TYPE  ExceptionType,
465  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
466  );
467
468
469/**
470 Periodic callback for GDB. This function is used to catch a ctrl-c or other
471 break in type command from GDB.
472
473 @param SystemContext           Register content at time of the call
474
475 **/
476VOID
477EFIAPI
478GdbPeriodicCallBack (
479  IN OUT EFI_SYSTEM_CONTEXT  SystemContext
480  );
481
482
483/**
484  Make two serail consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
485
486  These console show up on the remote system running GDB
487
488**/
489
490VOID
491GdbInitializeSerialConsole (
492  VOID
493  );
494
495
496/**
497  Send a GDB Remote Serial Protocol Packet
498
499  $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
500  the packet teminating character '#' and the two digit checksum.
501
502  If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up
503  in an infinit loop. This is so if you unplug the debugger code just keeps running
504
505  @param PacketData   Payload data for the packet
506
507  @retval             Number of bytes of packet data sent.
508
509**/
510UINTN
511SendPacket (
512  IN  CHAR8 *PacketData
513  );
514
515
516/**
517 Receive a GDB Remote Serial Protocol Packet
518
519 $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
520 the packet teminating character '#' and the two digit checksum.
521
522 If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed.
523 (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
524
525 If an ack '+' is not sent resend the packet
526
527 @param PacketData   Payload data for the packet
528
529 @retval             Number of bytes of packet data received.
530
531 **/
532UINTN
533ReceivePacket (
534 OUT  CHAR8 *PacketData,
535 IN   UINTN PacketDataSize
536 );
537
538
539/**
540  Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates
541  the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
542
543  @param  FileDescriptor   Device to talk to.
544  @param  Buffer           Buffer to hold Count bytes that were read
545  @param  Count            Number of bytes to transfer.
546
547  @retval -1               Error
548  @retval {other}          Number of bytes read.
549
550**/
551INTN
552GdbRead (
553  IN  INTN    FileDescriptor,
554  OUT VOID    *Buffer,
555  IN  UINTN   Count
556  );
557
558
559/**
560  Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates
561  nothing was written. On error -1 is returned.
562
563  @param  FileDescriptor   Device to talk to.
564  @param  Buffer           Buffer to hold Count bytes that are to be written
565  @param  Count            Number of bytes to transfer.
566
567  @retval -1               Error
568  @retval {other}          Number of bytes written.
569
570**/
571INTN
572GdbWrite (
573  IN  INTN          FileDescriptor,
574  OUT CONST VOID    *Buffer,
575  IN  UINTN         Count
576  );
577
578UINTN *
579FindPointerToRegister (
580  IN  EFI_SYSTEM_CONTEXT    SystemContext,
581  IN  UINTN                 RegNumber
582  );
583
584CHAR8 *
585BasicReadRegister (
586  IN  EFI_SYSTEM_CONTEXT      SystemContext,
587  IN  UINTN                   RegNumber,
588  IN  CHAR8                   *OutBufPtr
589  );
590
591VOID
592TransferFromInBufToMem (
593  IN  UINTN   Length,
594  IN  UINT8   *Address,
595  IN  CHAR8   *NewData
596  );
597
598VOID
599TransferFromMemToOutBufAndSend (
600  IN  UINTN  Length,
601  IN  UINT8  *Address
602  );
603
604CHAR8 *
605BasicWriteRegister (
606  IN  EFI_SYSTEM_CONTEXT    SystemContext,
607  IN  UINTN                 RegNumber,
608  IN  CHAR8                 *InBufPtr
609  );
610
611VOID
612PrintReg (
613  EFI_SYSTEM_CONTEXT SystemContext
614  );
615
616UINTN
617ParseBreakpointPacket (
618  IN  CHAR8 *PacketData,
619  OUT UINTN *Type,
620  OUT UINTN *Address,
621  OUT UINTN *Length
622  );
623
624UINTN
625GetBreakpointDataAddress (
626  IN  EFI_SYSTEM_CONTEXT  SystemContext,
627  IN  UINTN               BreakpointNumber
628  );
629
630UINTN
631GetBreakpointDetected (
632  IN  EFI_SYSTEM_CONTEXT  SystemContext
633  );
634
635BREAK_TYPE
636GetBreakpointType (
637  IN  EFI_SYSTEM_CONTEXT  SystemContext,
638  IN  UINTN               BreakpointNumber
639  );
640
641UINTN
642ConvertLengthData (
643  IN  UINTN  Length
644  );
645
646EFI_STATUS
647FindNextFreeDebugRegister (
648  IN  EFI_SYSTEM_CONTEXT  SystemContext,
649  OUT UINTN               *Register
650  );
651
652EFI_STATUS
653EnableDebugRegister (
654  IN  EFI_SYSTEM_CONTEXT  SystemContext,
655  IN  UINTN               Register,
656  IN  UINTN               Address,
657  IN  UINTN               Length,
658  IN  UINTN               Type
659  );
660
661EFI_STATUS
662FindMatchingDebugRegister (
663 IN  EFI_SYSTEM_CONTEXT  SystemContext,
664 IN  UINTN               Address,
665 IN  UINTN               Length,
666 IN  UINTN               Type,
667 OUT UINTN               *Register
668 );
669
670EFI_STATUS
671DisableDebugRegister (
672 IN  EFI_SYSTEM_CONTEXT  SystemContext,
673 IN  UINTN               Register
674 );
675
676VOID
677InitializeProcessor (
678  VOID
679  );
680
681/**
682 Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
683
684 @param  SystemContext        Register content at time of the exception
685 @param  GdbExceptionType     GDB exception type
686 **/
687VOID
688ProcessorSendTSignal (
689  IN  EFI_SYSTEM_CONTEXT  SystemContext,
690  IN  UINT8               GdbExceptionType,
691  IN  OUT CHAR8           *TSignalPtr,
692  IN  UINTN               SizeOfBuffer
693  );
694
695/**
696 Check to see if this exception is related to ctrl-c handling.
697
698 @param ExceptionType     Exception that is being processed
699 @param SystemContext     Register content at time of the exception
700
701 @return  TRUE  This was a ctrl-c check that did not find a ctrl-c
702 @return  FALSE This was not a ctrl-c check or some one hit ctrl-c
703 **/
704BOOLEAN
705ProcessorControlC (
706  IN  EFI_EXCEPTION_TYPE        ExceptionType,
707  IN OUT EFI_SYSTEM_CONTEXT     SystemContext
708  );
709
710
711/**
712  Initialize debug agent.
713
714  This function is used to set up debug enviroment. It may enable interrupts.
715
716  @param[in] InitFlag   Init flag is used to decide initialize process.
717  @param[in] Context    Context needed according to InitFlag, it was optional.
718
719**/
720VOID
721EFIAPI
722DebugAgentHookExceptions (
723  IN UINT32                InitFlag,
724  IN VOID                  *Context  OPTIONAL
725  );
726
727
728#endif
729