]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/GdbStub/GdbStubInternal.h
Adding support for BeagleBoard.
[mirror_edk2.git] / EmbeddedPkg / GdbStub / GdbStubInternal.h
diff --git a/EmbeddedPkg/GdbStub/GdbStubInternal.h b/EmbeddedPkg/GdbStub/GdbStubInternal.h
new file mode 100644 (file)
index 0000000..20231cf
--- /dev/null
@@ -0,0 +1,746 @@
+/** @file
+  Private include file for GDB stub
+
+  Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+  All rights reserved. This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __GDB_STUB_INTERNAL__
+#define __GDB_STUB_INTERNAL__
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/GdbSerialLib.h>
+#include <Library/PrintLib.h>
+
+#include <Protocol/DebugSupport.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/LoadedImage.h>
+#include <Guid/DebugImageInfoTable.h>
+#include <IndustryStandard/PeImage.h>
+
+extern CONST CHAR8 mHexToStr[];
+
+// maximum size of input and output buffers
+// This value came from the show remote command of the gdb we tested against 
+#define MAX_BUF_SIZE 2000
+
+// maximum size of address buffer
+#define MAX_ADDR_SIZE 32
+
+// maximum size of register number buffer
+#define MAX_REG_NUM_BUF_SIZE 32
+
+// maximum size of length buffer
+#define MAX_LENGTH_SIZE 32
+
+// maximum size of T signal members
+#define MAX_T_SIGNAL_SIZE 64
+
+// the mask used to clear all the cache
+#define TF_BIT 0x00000100
+
+
+//
+// GDB Signal definitions - generic names for interrupts
+//
+#define GDB_SIGILL      4  // Illegal instruction       
+#define GDB_SIGTRAP     5  // Trace Trap (Breakpoint and SingleStep)
+#define GDB_SIGEMT      7  // Emulator Trap
+#define GDB_SIGFPE      8  // Floating point exception
+#define GDB_SIGSEGV     11 // Setgment violation, page fault 
+
+
+//
+// GDB File I/O Error values, zero means no error
+// Includes all general GDB Unix like error values
+//
+#define GDB_EBADMEMADDRBUFSIZE   11  // the buffer that stores memory Address to be read from/written to is not the right size
+#define GDB_EBADMEMLENGBUFSIZE   12  // the buffer that stores Length is not the right size 
+#define GDB_EBADMEMLENGTH        13  // Length, the given number of bytes to read or write, is not the right size
+#define GDB_EBADMEMDATA          14  // one of the bytes or nibbles of the memory is leess than 0 
+#define GDB_EBADMEMDATASIZE      15  // the memory data, 'XX..', is too short or too long
+#define GDB_EBADBUFSIZE          21  // the buffer created is not the correct size
+#define GDB_EINVALIDARG          31  // argument is invalid
+#define GDB_ENOSPACE             41  //
+#define GDB_EINVALIDBRKPOINTTYPE 51  // the breakpoint type is not recognized
+#define GDB_EINVALIDREGNUM       61  // given register number is not valid: either <0 or >=Number of Registers
+#define GDB_EUNKNOWN             255 // unknown
+
+
+//
+// These devices are open by GDB so we can just read and write to them
+//
+#define GDB_STDIN   0x00
+#define GDB_STDOUT  0x01
+#define GDB_STDERR  0x02
+
+//
+//Define Register size for different architectures
+//
+#if defined (MDE_CPU_IA32) 
+#define REG_SIZE  32
+#elif defined (MDE_CPU_X64)
+#define REG_SIZE  64
+#elif defined (MDE_CPU_ARM)
+#define REG_SIZE  32
+#endif
+
+#define GDB_SERIAL_DEV_SIGNATURE    SIGNATURE_32 ('g', 'd', 'b', 's')
+
+typedef struct {
+  VENDOR_DEVICE_PATH                     VendorDevice;
+  UINT32                                 Index;         // Suport more than one
+  EFI_DEVICE_PATH_PROTOCOL               End;
+} GDB_SERIAL_DEVICE_PATH;
+
+//
+//  Name:   SERIAL_DEV
+//  Purpose:  To provide device specific information
+//  Fields:
+//      Signature UINTN: The identity of the serial device
+//      SerialIo  SERIAL_IO_PROTOCOL: Serial I/O protocol interface
+//      SerialMode  SERIAL_IO_MODE:
+//      DevicePath  EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device
+//
+typedef struct {
+  UINTN                                  Signature;
+  EFI_HANDLE                             Handle;
+  EFI_SERIAL_IO_PROTOCOL                 SerialIo;
+  EFI_SERIAL_IO_MODE                     SerialMode;
+  GDB_SERIAL_DEVICE_PATH                 DevicePath;
+  INTN                                   InFileDescriptor;
+  INTN                                   OutFileDescriptor;
+} GDB_SERIAL_DEV;
+
+
+#define GDB_SERIAL_DEV_FROM_THIS(a) CR (a, GDB_SERIAL_DEV, SerialIo, GDB_SERIAL_DEV_SIGNATURE)
+
+
+typedef struct {
+    EFI_EXCEPTION_TYPE  Exception;
+    UINT8               SignalNo;
+} EFI_EXCEPTION_TYPE_ENTRY;
+
+
+#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
+
+//
+// Byte packed structure for DR6
+// 32-bits on IA-32
+// 64-bits on X64.  The upper 32-bits on X64 are reserved
+//
+typedef union {
+  struct {
+    UINT32  B0:1;           // Breakpoint condition detected
+    UINT32  B1:1;           // Breakpoint condition detected
+    UINT32  B2:1;           // Breakpoint condition detected
+    UINT32  B3:1;           // Breakpoint condition detected
+    UINT32  Reserved_1:9;   // Reserved 
+    UINT32  BD:1;           // Debug register access detected
+    UINT32  BS:1;           // Single step
+    UINT32  BT:1;           // Task switch
+    UINT32  Reserved_2:16;  // Reserved
+  } Bits;
+  UINTN     UintN;
+} IA32_DR6;
+
+//
+// Byte packed structure for DR7
+// 32-bits on IA-32
+// 64-bits on X64.  The upper 32-bits on X64 are reserved
+//
+typedef union {
+  struct {
+    UINT32  L0:1;           // Local breakpoint enable
+    UINT32  G0:1;           // Global breakpoint enable
+    UINT32  L1:1;           // Local breakpoint enable
+    UINT32  G1:1;           // Global breakpoint enable
+    UINT32  L2:1;           // Local breakpoint enable
+    UINT32  G2:1;           // Global breakpoint enable
+    UINT32  L3:1;           // Local breakpoint enable
+    UINT32  G3:1;           // Global breakpoint enable
+    UINT32  LE:1;           // Local exact breakpoint enable
+    UINT32  GE:1;           // Global exact breakpoint enable
+    UINT32  Reserved_1:3;   // Reserved
+    UINT32  GD:1;           // Global detect enable
+    UINT32  Reserved_2:2;   // Reserved
+    UINT32  RW0:2;          // Read/Write field
+    UINT32  LEN0:2;         // Length field
+    UINT32  RW1:2;          // Read/Write field
+    UINT32  LEN1:2;         // Length field
+    UINT32  RW2:2;          // Read/Write field
+    UINT32  LEN2:2;         // Length field
+    UINT32  RW3:2;          // Read/Write field
+    UINT32  LEN3:2;         // Length field
+  } Bits;
+  UINTN     UintN;
+} IA32_DR7;
+
+#endif /* if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) */
+
+typedef enum {
+  InstructionExecution,   //Hardware breakpoint
+  DataWrite,              //watch
+  DataRead,               //rwatch
+  DataReadWrite,          //awatch
+  SoftwareBreakpoint,     //Software breakpoint
+  NotSupported
+} BREAK_TYPE;
+
+//
+// Array of exception types that need to be hooked by the debugger
+//
+extern EFI_EXCEPTION_TYPE_ENTRY gExceptionType[];
+
+//
+// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c
+// here we need to wait for the periodic callback to do this. 
+//
+extern BOOLEAN gCtrlCBreakFlag;
+
+//
+// If the periodic callback is called while we are processing an F packet we need
+// to let the callback know to not read from the serail stream as it could steal
+// characters from the F reponse packet
+//
+extern BOOLEAN gProcessingFPacket;
+
+
+// The offsets of registers SystemContext.
+// The fields in the array are in the gdb ordering.
+//
+extern UINTN    gRegisterOffsets[];
+
+/**
+ Return the number of entries in the gExceptionType[]
+ @retval    UINTN, the number of entries in the gExceptionType[] array.    
+ **/
+UINTN
+MaxEfiException (
+  VOID
+  );
+
+
+/**
+ Return the number of entries in the gRegisters[]
+ @retval    UINTN, the number of entries (registers) in the gRegisters[] array.    
+ **/
+UINTN
+MaxRegisterCount (
+  VOID
+  );
+
+
+/**
+ Check to see if the ISA is supported. 
+ ISA = Instruction Set Architecture
+ @retval    TRUE if Isa is supported,
+ FALSE otherwise.
+ **/
+BOOLEAN
+CheckIsa (
+  IN    EFI_INSTRUCTION_SET_ARCHITECTURE    Isa
+  );
+
+
+/**
+ Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
+ @param  SystemContext        Register content at time of the exception
+ @param  GdbExceptionType     GDB exception type
+ **/
+
+VOID
+GdbSendTSignal (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  IN  UINT8                  GdbExceptionType
+  );
+
+
+/**
+ Translates the EFI mapping to GDB mapping
+ @param     EFIExceptionType        EFI Exception that is being processed
+ @retval    UINTN that corresponds to EFIExceptionType's GDB exception type number
+ **/
+UINT8
+ConvertEFItoGDBtype ( 
+  IN  EFI_EXCEPTION_TYPE EFIExceptionType
+  );
+
+
+/**
+ Empties the given buffer 
+ @param *Buf pointer to the first element in buffer to be emptied
+ **/
+VOID
+EmptyBuffer ( 
+  IN CHAR8  *Buf
+  );
+
+
+/**
+ Converts an 8-bit Hex Char into a INTN.
+ @param     Char  - the hex character to be converted into UINTN
+ @retval    a INTN, from 0 to 15, that corressponds to Char
+ -1 if Char is not a hex character
+ **/
+INTN
+HexCharToInt (
+  IN  CHAR8 Char
+  );
+
+
+/** 'E NN'
+ Send an error with the given error number after converting to hex.
+ The error number is put into the buffer in hex. '255' is the biggest errno we can send.
+ ex: 162 will be sent as A2.
+ @param   errno    the error number that will be sent
+ **/
+VOID
+EFIAPI
+SendError (
+  IN  UINT8     ErrorNum
+  );
+
+
+/**
+ Send 'OK' when the function is done executing successfully.
+ **/
+VOID
+SendSuccess (
+  VOID
+  );
+
+
+/**
+ Send empty packet to specify that particular command/functionality is not supported.
+ **/
+VOID
+SendNotSupported (
+  VOID
+  );
+
+/** ‘p n’ 
+ Reads the n-th register's value into an output buffer and sends it as a packet 
+ @param     SystemContext       Register content at time of the exception
+ @param     InBuffer            This is the input buffer received from gdb server
+ **/
+VOID
+ReadNthRegister (
+  IN    EFI_SYSTEM_CONTEXT  SystemContext,
+  IN    CHAR8               *InBuffer
+  );
+
+
+/** ‘g’ 
+ Reads the general registers into an output buffer  and sends it as a packet 
+ @param     SystemContext           Register content at time of the exception
+ **/
+VOID
+ReadGeneralRegisters (  
+  IN    EFI_SYSTEM_CONTEXT  SystemContext
+  );
+
+
+/** ‘P n...=r...’
+ Writes the new value of n-th register received into the input buffer to the n-th register
+ @param     SystemContext       Register content at time of the exception
+ @param     InBuffer            This is the input buffer received from gdb server
+ **/
+VOID
+WriteNthRegister (
+  IN    EFI_SYSTEM_CONTEXT  SystemContext,
+  IN    CHAR8               *InBuffer
+  );
+
+
+/** ‘G XX...’
+ Writes the new values received into the input buffer to the general registers
+ @param     SystemContext               Register content at time of the exception
+ @param     InBuffer                    Pointer to the input buffer received from gdb server
+ **/
+
+VOID
+WriteGeneralRegisters (
+  IN    EFI_SYSTEM_CONTEXT  SystemContext,
+  IN    CHAR8               *InBuffer
+  );
+
+
+/** ‘m addr,length ’
+ Find the Length of the area to read and the start addres. Finally, pass them to 
+ another function, TransferFromMemToOutBufAndSend, that will read from that memory space and 
+ send it as a packet.
+ @param  *PacketData  Pointer to Payload data for the packet
+ **/
+VOID
+ReadFromMemory (
+  IN  CHAR8  *PacketData
+  );
+
+
+/** ‘M addr,length :XX...’
+ Find the Length of the area in bytes to write and the start addres. Finally, pass them to 
+ another function, TransferFromInBufToMem, that will write to that memory space the info in
+ the input buffer.
+ @param   PacketData     Pointer to Payload data for the packet
+ **/
+VOID
+WriteToMemory (
+  IN CHAR8 *PacketData
+  );
+
+
+/** ‘c [addr ]’ 
+ Continue. addr is Address to resume. If addr is omitted, resume at current 
+ Address.
+ @param SystemContext Register content at time of the exception  
+ @param *PacketData   Pointer to PacketData
+ **/
+
+VOID
+ContinueAtAddress (
+  IN  EFI_SYSTEM_CONTEXT   SystemContext,
+  IN  CHAR8                *PacketData
+  );
+
+
+/** ‘s [addr ]’
+ Single step. addr is the Address at which to resume. If addr is omitted, resume 
+ at same Address.
+ @param SystemContext   Register content at time of the exception
+ @param PacketData      Pointer to Payload data for the packet
+ **/
+VOID
+SingleStep (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  IN  CHAR8               *PacketData
+  );
+
+/** 
+ Insert Single Step in the SystemContext
+ @param SystemContext   Register content at time of the exception
+ **/
+VOID
+AddSingleStep (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext
+  );
+  
+/** 
+ Remove Single Step in the SystemContext
+ @param SystemContext   Register content at time of the exception
+ **/
+VOID
+RemoveSingleStep (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext
+  );
+  
+  
+/**
+  ‘Z1, [addr], [length]’
+  ‘Z2, [addr], [length]’
+  ‘Z3, [addr], [length]’
+  ‘Z4, [addr], [length]’
+
+  Insert hardware breakpoint/watchpoint at address addr of size length
+
+  @param SystemContext  Register content at time of the exception
+  @param *PacketData    Pointer to the Payload data for the packet
+
+**/
+VOID
+EFIAPI
+InsertBreakPoint(
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  IN  CHAR8               *PacketData
+  );
+
+
+/**
+  ‘z1, [addr], [length]’
+  ‘z2, [addr], [length]’
+  ‘z3, [addr], [length]’
+  ‘z4, [addr], [length]’
+
+  Remove hardware breakpoint/watchpoint at address addr of size length
+
+  @param SystemContext  Register content at time of the exception
+  @param *PacketData    Pointer to the Payload data for the packet
+
+**/
+VOID
+EFIAPI
+RemoveBreakPoint(
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  IN  CHAR8               *PacketData
+  );
+
+
+/**
+ Exception Hanldler for GDB. It will be called for all exceptions
+ registered via the gExceptionType[] array.
+ @param ExceptionType   Exception that is being processed
+ @param SystemContext   Register content at time of the exception  
+ **/
+VOID
+EFIAPI
+GdbExceptionHandler ( 
+  IN     EFI_EXCEPTION_TYPE  ExceptionType, 
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext 
+  );
+
+
+/**
+ Periodic callback for GDB. This function is used to catch a ctrl-c or other 
+ break in type command from GDB.
+ @param SystemContext           Register content at time of the call
+ **/
+VOID
+EFIAPI
+GdbPeriodicCallBack ( 
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext 
+  );
+
+
+/**
+  Make two serail consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
+  
+  These console show up on the remote system running GDB
+
+**/
+
+VOID
+GdbInitializeSerialConsole (
+  VOID
+  );
+
+
+/**
+  Send a GDB Remote Serial Protocol Packet
+  
+  $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', 
+  the packet teminating character '#' and the two digit checksum.
+  
+  If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up 
+  in an infinit loop. This is so if you unplug the debugger code just keeps running
+
+  @param PacketData   Payload data for the packet  
+  
+  @retval             Number of bytes of packet data sent.
+
+**/
+UINTN
+SendPacket (
+  IN  CHAR8 *PacketData
+  );
+  
+
+/**
+ Receive a GDB Remote Serial Protocol Packet
+ $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', 
+ the packet teminating character '#' and the two digit checksum.
+ If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed.
+ (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
+ If an ack '+' is not sent resend the packet
+ @param PacketData   Payload data for the packet  
+ @retval             Number of bytes of packet data received.
+
+ **/
+UINTN
+ReceivePacket (
+ OUT  CHAR8 *PacketData,
+ IN   UINTN PacketDataSize
+ );
+  
+
+/**
+  Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates 
+  the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
+
+  @param  FileDescriptor   Device to talk to.
+  @param  Buffer           Buffer to hold Count bytes that were read
+  @param  Count            Number of bytes to transfer. 
+
+  @retval -1               Error
+  @retval {other}          Number of bytes read.
+
+**/
+INTN
+GdbRead (
+  IN  INTN    FileDescriptor,
+  OUT VOID    *Buffer,
+  IN  UINTN   Count
+  );
+  
+
+/**
+  Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates 
+  nothing was written. On error -1 is returned. 
+
+  @param  FileDescriptor   Device to talk to.
+  @param  Buffer           Buffer to hold Count bytes that are to be written
+  @param  Count            Number of bytes to transfer. 
+
+  @retval -1               Error
+  @retval {other}          Number of bytes written.
+
+**/
+INTN
+GdbWrite (
+  IN  INTN          FileDescriptor,
+  OUT CONST VOID    *Buffer,
+  IN  UINTN         Count
+  );
+
+UINTN *  
+FindPointerToRegister (
+  IN  EFI_SYSTEM_CONTEXT    SystemContext,
+  IN  UINTN                 RegNumber  
+  );
+
+CHAR8 * 
+BasicReadRegister (
+  IN  EFI_SYSTEM_CONTEXT      SystemContext,
+  IN  UINTN                   RegNumber,
+  IN  CHAR8                   *OutBufPtr
+  );
+
+VOID
+TransferFromInBufToMem (
+  IN  UINTN   Length,
+  IN  UINT8   *Address,
+  IN  CHAR8   *NewData
+  );
+
+VOID
+TransferFromMemToOutBufAndSend (
+  IN  UINTN  Length,
+  IN  UINT8  *Address
+  );
+
+CHAR8 *
+BasicWriteRegister (
+  IN  EFI_SYSTEM_CONTEXT    SystemContext,
+  IN  UINTN                 RegNumber,
+  IN  CHAR8                 *InBufPtr
+  );
+
+VOID  
+PrintReg (
+  EFI_SYSTEM_CONTEXT SystemContext
+  );
+
+UINTN
+ParseBreakpointPacket (
+  IN  CHAR8 *PacketData,
+  OUT UINTN *Type,
+  OUT UINTN *Address,
+  OUT UINTN *Length
+  );
+
+UINTN
+GetBreakpointDataAddress (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  IN  UINTN               BreakpointNumber 
+  );
+
+UINTN
+GetBreakpointDetected (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext
+  );
+
+BREAK_TYPE
+GetBreakpointType (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  IN  UINTN               BreakpointNumber  
+  );
+
+UINTN
+ConvertLengthData (
+  IN  UINTN  Length
+  );
+
+EFI_STATUS
+FindNextFreeDebugRegister (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  OUT UINTN               *Register
+  );
+
+EFI_STATUS
+EnableDebugRegister (
+  IN  EFI_SYSTEM_CONTEXT  SystemContext,
+  IN  UINTN               Register,
+  IN  UINTN               Address,
+  IN  UINTN               Length,
+  IN  UINTN               Type
+  );
+
+EFI_STATUS
+FindMatchingDebugRegister (
+ IN  EFI_SYSTEM_CONTEXT  SystemContext,
+ IN  UINTN               Address,
+ IN  UINTN               Length,
+ IN  UINTN               Type,
+ OUT UINTN               *Register
+ );
+
+EFI_STATUS
+DisableDebugRegister (
+ IN  EFI_SYSTEM_CONTEXT  SystemContext,
+ IN  UINTN               Register
+ );
+
+VOID
+InitializeProcessor (
+  VOID
+  );
+
+BOOLEAN
+ValidateAddress (
+  IN  VOID  *Address
+  );
+
+BOOLEAN
+ValidateException (
+  IN  EFI_EXCEPTION_TYPE    ExceptionType, 
+  IN OUT EFI_SYSTEM_CONTEXT SystemContext 
+  );
+
+#endif