Home | History | Annotate | Download | only in Ia32
      1 /** @file
      2   Processor specific parts of the 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 #include <GdbDebugAgent.h>
     17 
     18 //
     19 // Array of exception types that need to be hooked by the debugger
     20 // {EFI mapping, GDB mapping}
     21 //
     22 EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
     23   { EXCEPT_IA32_DIVIDE_ERROR,     GDB_SIGFPE  },
     24   { EXCEPT_IA32_DEBUG,            GDB_SIGTRAP },
     25   { EXCEPT_IA32_NMI,              GDB_SIGEMT  },
     26   { EXCEPT_IA32_BREAKPOINT,       GDB_SIGTRAP },
     27   { EXCEPT_IA32_OVERFLOW,         GDB_SIGSEGV },
     28   { EXCEPT_IA32_BOUND,            GDB_SIGSEGV },
     29   { EXCEPT_IA32_INVALID_OPCODE,   GDB_SIGILL  },
     30   { EXCEPT_IA32_DOUBLE_FAULT,     GDB_SIGEMT  },
     31   { EXCEPT_IA32_STACK_FAULT,      GDB_SIGSEGV },
     32   { EXCEPT_IA32_GP_FAULT,         GDB_SIGSEGV },
     33   { EXCEPT_IA32_PAGE_FAULT,       GDB_SIGSEGV },
     34   { EXCEPT_IA32_FP_ERROR,         GDB_SIGEMT  },
     35   { EXCEPT_IA32_ALIGNMENT_CHECK,  GDB_SIGEMT  },
     36   { EXCEPT_IA32_MACHINE_CHECK,    GDB_SIGEMT  }
     37 };
     38 
     39 
     40 // The offsets of registers SystemContext.
     41 // The fields in the array are in the gdb ordering.
     42 //
     43 //16 regs
     44 UINTN gRegisterOffsets[] = {
     45   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eax),
     46   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ecx),
     47   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edx),
     48   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebx),
     49   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esp),
     50   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebp),
     51   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esi),
     52   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edi),
     53   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eip),
     54   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eflags),
     55   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Cs),
     56   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ss),
     57   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ds),
     58   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Es),
     59   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Fs),
     60   OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Gs)
     61 };
     62 
     63 
     64 //Debug only..
     65 VOID
     66 PrintReg (
     67   IN EFI_SYSTEM_CONTEXT SystemContext
     68   )
     69 {
     70   Print ((CHAR16 *)L"EAX: %x ", SystemContext.SystemContextIa32->Eax);
     71   Print ((CHAR16 *)L"ECX: %x ", SystemContext.SystemContextIa32->Ecx);
     72   Print ((CHAR16 *)L"EDX: %x ", SystemContext.SystemContextIa32->Edx);
     73   Print ((CHAR16 *)L"EBX: %x ", SystemContext.SystemContextIa32->Ebx);
     74   Print ((CHAR16 *)L"ESP: %x ", SystemContext.SystemContextIa32->Esp);
     75   Print ((CHAR16 *)L"EBP: %x ", SystemContext.SystemContextIa32->Ebp);
     76   Print ((CHAR16 *)L"ESI: %x ", SystemContext.SystemContextIa32->Esi);
     77   Print ((CHAR16 *)L"EDI: %x ", SystemContext.SystemContextIa32->Edi);
     78   Print ((CHAR16 *)L"EIP: %x\n", SystemContext.SystemContextIa32->Eip);
     79   Print ((CHAR16 *)L"EFlags: %x\n", SystemContext.SystemContextIa32->Eflags);
     80 }
     81 
     82 //Debug only..
     83 VOID
     84 PrintDRreg (
     85   IN EFI_SYSTEM_CONTEXT SystemContext
     86   )
     87 {
     88   Print ((CHAR16 *)L"DR0: %x ", SystemContext.SystemContextIa32->Dr0);
     89   Print ((CHAR16 *)L"DR1: %x ", SystemContext.SystemContextIa32->Dr1);
     90   Print ((CHAR16 *)L"DR2: %x ", SystemContext.SystemContextIa32->Dr2);
     91   Print ((CHAR16 *)L"DR3: %x ", SystemContext.SystemContextIa32->Dr3);
     92   Print ((CHAR16 *)L"DR6: %x ", SystemContext.SystemContextIa32->Dr6);
     93   Print ((CHAR16 *)L"DR7: %x\n", SystemContext.SystemContextIa32->Dr7);
     94 }
     95 
     96 
     97 /**
     98  Return the number of entries in the gExceptionType[]
     99 
    100  @retval  UINTN, the number of entries in the gExceptionType[] array.
    101  **/
    102 UINTN
    103 MaxEfiException (
    104   VOID
    105   )
    106 {
    107   return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
    108 }
    109 
    110 
    111 /**
    112   Check to see if the ISA is supported.
    113   ISA = Instruction Set Architecture
    114 
    115   @retval TRUE if Isa is supported,
    116       FALSE otherwise.
    117 **/
    118 BOOLEAN
    119 CheckIsa (
    120   IN  EFI_INSTRUCTION_SET_ARCHITECTURE  Isa
    121   )
    122 {
    123   return (BOOLEAN)(Isa == IsaIa32);
    124 }
    125 
    126 
    127 /**
    128  This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
    129  It is, by default, set to find the register pointer of the IA32 member
    130 
    131  @param   SystemContext     Register content at time of the exception
    132  @param   RegNumber       The register to which we want to find a pointer
    133  @retval  the pointer to the RegNumber-th pointer
    134  **/
    135 UINTN *
    136 FindPointerToRegister(
    137   IN  EFI_SYSTEM_CONTEXT  SystemContext,
    138   IN  UINTN               RegNumber
    139   )
    140 {
    141   UINT8 *TempPtr;
    142   TempPtr = ((UINT8 *)SystemContext.SystemContextIa32) + gRegisterOffsets[RegNumber];
    143   return (UINTN *)TempPtr;
    144 }
    145 
    146 
    147 /**
    148  Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
    149 
    150  @param SystemContext     Register content at time of the exception
    151  @param   RegNumber       the number of the register that we want to read
    152  @param   OutBufPtr       pointer to the output buffer's end. the new data will be added from this point on.
    153  @retval  the pointer to the next character of the output buffer that is available to be written on.
    154  **/
    155 CHAR8 *
    156 BasicReadRegister (
    157   IN  EFI_SYSTEM_CONTEXT      SystemContext,
    158   IN  UINTN           RegNumber,
    159   IN  CHAR8           *OutBufPtr
    160   )
    161 {
    162   UINTN RegSize;
    163 
    164   RegSize = 0;
    165   while (RegSize < REG_SIZE) {
    166     *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
    167     *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
    168     RegSize = RegSize + 8;
    169   }
    170   return OutBufPtr;
    171 }
    172 
    173 
    174 /** p n
    175  Reads the n-th register's value into an output buffer and sends it as a packet
    176 
    177  @param   SystemContext   Register content at time of the exception
    178  @param   InBuffer      Pointer to the input buffer received from gdb server
    179  **/
    180 VOID
    181 EFIAPI
    182 ReadNthRegister (
    183   IN  EFI_SYSTEM_CONTEXT   SystemContext,
    184   IN  CHAR8                *InBuffer
    185   )
    186 {
    187   UINTN RegNumber;
    188   CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
    189   CHAR8 *OutBufPtr;   // pointer to the output buffer
    190 
    191   RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
    192 
    193   if ((RegNumber < 0) || (RegNumber >= sizeof (gRegisterOffsets)/sizeof (UINTN))) {
    194     SendError (GDB_EINVALIDREGNUM);
    195     return;
    196   }
    197 
    198   OutBufPtr = OutBuffer;
    199   OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr);
    200 
    201   *OutBufPtr = '\0';  // the end of the buffer
    202   SendPacket(OutBuffer);
    203 }
    204 
    205 
    206 /** g
    207  Reads the general registers into an output buffer  and sends it as a packet
    208 
    209  @param   SystemContext     Register content at time of the exception
    210  **/
    211 VOID
    212 EFIAPI
    213 ReadGeneralRegisters (
    214   IN  EFI_SYSTEM_CONTEXT      SystemContext
    215   )
    216 {
    217   UINTN   i;
    218   CHAR8 OutBuffer[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
    219   CHAR8 *OutBufPtr;   // pointer to the output buffer
    220 
    221   OutBufPtr = OutBuffer;
    222   for(i = 0 ; i < sizeof (gRegisterOffsets)/sizeof (UINTN) ; i++) {  // there are only 16 registers to read
    223     OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr);
    224   }
    225 
    226   *OutBufPtr = '\0';  // the end of the buffer
    227   SendPacket(OutBuffer);
    228 }
    229 
    230 
    231 /**
    232  Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
    233 
    234  @param   SystemContext       Register content at time of the exception
    235  @param   RegNumber         the number of the register that we want to write
    236  @param   InBufPtr          pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
    237  @retval  the pointer to the next character of the input buffer that can be used
    238  **/
    239 CHAR8 *
    240 BasicWriteRegister (
    241   IN  EFI_SYSTEM_CONTEXT      SystemContext,
    242   IN  UINTN           RegNumber,
    243   IN  CHAR8           *InBufPtr
    244   )
    245 {
    246   UINTN RegSize;
    247   UINTN TempValue; // the value transferred from a hex char
    248   UINT32 NewValue; // the new value of the RegNumber-th Register
    249 
    250   NewValue = 0;
    251   RegSize = 0;
    252   while (RegSize < REG_SIZE) {
    253     TempValue = HexCharToInt(*InBufPtr++);
    254 
    255    if (TempValue < 0) {
    256       SendError (GDB_EBADMEMDATA);
    257       return NULL;
    258     }
    259 
    260     NewValue += (TempValue << (RegSize+4));
    261     TempValue = HexCharToInt(*InBufPtr++);
    262 
    263     if (TempValue < 0) {
    264       SendError (GDB_EBADMEMDATA);
    265       return NULL;
    266     }
    267 
    268     NewValue += (TempValue << RegSize);
    269     RegSize = RegSize + 8;
    270   }
    271   *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
    272   return InBufPtr;
    273 }
    274 
    275 
    276 /** P n...=r...
    277  Writes the new value of n-th register received into the input buffer to the n-th register
    278 
    279  @param   SystemContext   Register content at time of the exception
    280  @param   InBuffer      Ponter to the input buffer received from gdb server
    281  **/
    282 VOID
    283 EFIAPI
    284 WriteNthRegister (
    285   IN  EFI_SYSTEM_CONTEXT      SystemContext,
    286   IN  CHAR8           *InBuffer
    287   )
    288 {
    289   UINTN RegNumber;
    290   CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE];  // put the 'n..' part of the message into this array
    291   CHAR8 *RegNumBufPtr;
    292   CHAR8 *InBufPtr; // pointer to the input buffer
    293 
    294   // find the register number to write
    295   InBufPtr = &InBuffer[1];
    296   RegNumBufPtr = RegNumBuffer;
    297   while (*InBufPtr != '=') {
    298     *RegNumBufPtr++ = *InBufPtr++;
    299   }
    300   *RegNumBufPtr = '\0';
    301   RegNumber = AsciiStrHexToUintn (RegNumBuffer);
    302 
    303   // check if this is a valid Register Number
    304   if ((RegNumber < 0) || (RegNumber >= sizeof (gRegisterOffsets)/sizeof (UINTN))) {
    305     SendError (GDB_EINVALIDREGNUM);
    306     return;
    307   }
    308   InBufPtr++;  // skips the '=' character
    309   BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
    310   SendSuccess();
    311 }
    312 
    313 
    314 /** G XX...
    315  Writes the new values received into the input buffer to the general registers
    316 
    317  @param   SystemContext       Register content at time of the exception
    318  @param   InBuffer          Pointer to the input buffer received from gdb server
    319  **/
    320 VOID
    321 EFIAPI
    322 WriteGeneralRegisters (
    323   IN  EFI_SYSTEM_CONTEXT        SystemContext,
    324   IN  CHAR8             *InBuffer
    325   )
    326 {
    327   UINTN  i;
    328   CHAR8 *InBufPtr; /// pointer to the input buffer
    329 
    330   // check to see if the buffer is the right size which is
    331   // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129
    332   if (AsciiStrLen(InBuffer) != 129) { // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
    333     //Bad message. Message is not the right length
    334     SendError (GDB_EBADBUFSIZE);
    335     return;
    336   }
    337 
    338   InBufPtr = &InBuffer[1];
    339 
    340   // Read the new values for the registers from the input buffer to an array, NewValueArray.
    341   // The values in the array are in the gdb ordering
    342   for(i=0; i < sizeof (gRegisterOffsets)/sizeof (UINTN); i++) {  // there are only 16 registers to write
    343     InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr);
    344   }
    345 
    346   SendSuccess();
    347 }
    348 
    349 /** c [addr ]
    350  Continue. addr is Address to resume. If addr is omitted, resume at current
    351  Address.
    352 
    353  @param   SystemContext     Register content at time of the exception
    354  **/
    355 VOID
    356 EFIAPI
    357 ContinueAtAddress (
    358   IN  EFI_SYSTEM_CONTEXT      SystemContext,
    359   IN    CHAR8                 *PacketData
    360   )
    361 {
    362   if (PacketData[1] != '\0') {
    363     SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);
    364   }
    365 }
    366 
    367 
    368 /** s [addr ]
    369  Single step. addr is the Address at which to resume. If addr is omitted, resume
    370  at same Address.
    371 
    372  @param   SystemContext     Register content at time of the exception
    373  **/
    374 VOID
    375 EFIAPI
    376 SingleStep (
    377   IN  EFI_SYSTEM_CONTEXT      SystemContext,
    378   IN    CHAR8                 *PacketData
    379   )
    380 {
    381   SendNotSupported();
    382 }
    383 
    384 
    385 /**
    386   Returns breakpoint data address from DR0-DR3 based on the input breakpoint number
    387 
    388   @param  SystemContext      Register content at time of the exception
    389   @param  BreakpointNumber   Breakpoint number
    390 
    391   @retval Address            Data address from DR0-DR3 based on the breakpoint number.
    392 
    393 **/
    394 UINTN
    395 GetBreakpointDataAddress (
    396   IN  EFI_SYSTEM_CONTEXT  SystemContext,
    397   IN  UINTN               BreakpointNumber
    398   )
    399 {
    400   UINTN Address;
    401 
    402   if (BreakpointNumber == 1) {
    403     Address = SystemContext.SystemContextIa32->Dr0;
    404   } else if (BreakpointNumber == 2) {
    405     Address = SystemContext.SystemContextIa32->Dr1;
    406   } else if (BreakpointNumber == 3) {
    407     Address = SystemContext.SystemContextIa32->Dr2;
    408   } else if (BreakpointNumber == 4) {
    409     Address = SystemContext.SystemContextIa32->Dr3;
    410   } else {
    411     Address = 0;
    412   }
    413 
    414   return Address;
    415 }
    416 
    417 
    418 /**
    419   Returns currently detected breakpoint value based on the register DR6 B0-B3 field.
    420   If no breakpoint is detected then it returns 0.
    421 
    422   @param  SystemContext  Register content at time of the exception
    423 
    424   @retval {1-4}          Currently detected breakpoint value
    425   @retval 0              No breakpoint detected.
    426 
    427 **/
    428 UINTN
    429 GetBreakpointDetected (
    430   IN  EFI_SYSTEM_CONTEXT  SystemContext
    431   )
    432 {
    433   IA32_DR6 Dr6;
    434   UINTN BreakpointNumber;
    435 
    436   Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
    437 
    438   if (Dr6.Bits.B0 == 1) {
    439     BreakpointNumber = 1;
    440   } else if (Dr6.Bits.B1 == 1) {
    441     BreakpointNumber = 2;
    442   } else if (Dr6.Bits.B2 == 1) {
    443     BreakpointNumber = 3;
    444   } else if (Dr6.Bits.B3 == 1) {
    445     BreakpointNumber = 4;
    446   } else {
    447     BreakpointNumber = 0;  //No breakpoint detected
    448   }
    449 
    450   return BreakpointNumber;
    451 }
    452 
    453 
    454 /**
    455   Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite)
    456   based on the Breakpoint number
    457 
    458   @param  SystemContext        Register content at time of the exception
    459   @param  BreakpointNumber     Breakpoint number
    460 
    461   @retval BREAK_TYPE           Breakpoint type value read from register DR7 RWn field
    462                                For unknown value, it returns NotSupported.
    463 
    464 **/
    465 BREAK_TYPE
    466 GetBreakpointType (
    467   IN  EFI_SYSTEM_CONTEXT  SystemContext,
    468   IN  UINTN               BreakpointNumber
    469   )
    470 {
    471   IA32_DR7 Dr7;
    472   BREAK_TYPE Type = NotSupported;  //Default is NotSupported type
    473 
    474   Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
    475 
    476   if (BreakpointNumber == 1) {
    477     Type = (BREAK_TYPE) Dr7.Bits.RW0;
    478   } else if (BreakpointNumber == 2) {
    479     Type = (BREAK_TYPE) Dr7.Bits.RW1;
    480   } else if (BreakpointNumber == 3) {
    481     Type = (BREAK_TYPE) Dr7.Bits.RW2;
    482   } else if (BreakpointNumber == 4) {
    483     Type = (BREAK_TYPE) Dr7.Bits.RW3;
    484   }
    485 
    486   return Type;
    487 }
    488 
    489 
    490 /**
    491   Parses Length and returns the length which DR7 LENn field accepts.
    492   For example: If we receive 1-Byte length then we should return 0.
    493                Zero gets written to DR7 LENn field.
    494 
    495   @param  Length  Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
    496 
    497   @retval Length  Appropriate converted values which DR7 LENn field accepts.
    498 
    499 **/
    500 UINTN
    501 ConvertLengthData (
    502   IN     UINTN   Length
    503   )
    504 {
    505   if (Length == 1) {         //1-Byte length
    506     return 0;
    507   } else if (Length == 2) {  //2-Byte length
    508     return 1;
    509   } else if (Length == 4) {  //4-Byte length
    510     return 3;
    511   } else {                   //Undefined or 8-byte length
    512     return 2;
    513   }
    514 }
    515 
    516 
    517 /**
    518   Finds the next free debug register. If all the registers are occupied then
    519   EFI_OUT_OF_RESOURCES is returned.
    520 
    521   @param  SystemContext   Register content at time of the exception
    522   @param  Register        Register value (0 - 3 for the first free debug register)
    523 
    524   @retval EFI_STATUS      Appropriate status value.
    525 
    526 **/
    527 EFI_STATUS
    528 FindNextFreeDebugRegister (
    529   IN  EFI_SYSTEM_CONTEXT  SystemContext,
    530   OUT UINTN               *Register
    531   )
    532 {
    533   IA32_DR7 Dr7;
    534 
    535   Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
    536 
    537   if (Dr7.Bits.G0 == 0) {
    538     *Register = 0;
    539   } else if (Dr7.Bits.G1 == 0) {
    540     *Register = 1;
    541   } else if (Dr7.Bits.G2 == 0) {
    542     *Register = 2;
    543   } else if (Dr7.Bits.G3 == 0) {
    544     *Register = 3;
    545   } else {
    546     return EFI_OUT_OF_RESOURCES;
    547   }
    548 
    549   return EFI_SUCCESS;
    550 }
    551 
    552 
    553 /**
    554   Enables the debug register. Writes Address value to appropriate DR0-3 register.
    555   Sets LENn, Gn, RWn bits in DR7 register.
    556 
    557   @param  SystemContext   Register content at time of the exception
    558   @param  Register        Register value (0 - 3)
    559   @param  Address         Breakpoint address value
    560   @param  Type            Breakpoint type (Instruction, Data write, Data read
    561                           or write etc.)
    562 
    563   @retval EFI_STATUS      Appropriate status value.
    564 
    565 **/
    566 EFI_STATUS
    567 EnableDebugRegister (
    568   IN  EFI_SYSTEM_CONTEXT  SystemContext,
    569   IN  UINTN               Register,
    570   IN  UINTN               Address,
    571   IN  UINTN               Length,
    572   IN  UINTN               Type
    573   )
    574 {
    575   IA32_DR7  Dr7;
    576 
    577   //Convert length data
    578   Length = ConvertLengthData (Length);
    579 
    580   //For Instruction execution, length should be 0
    581   //(Ref. Intel reference manual 18.2.4)
    582   if ((Type == 0) && (Length != 0)) {
    583     return EFI_INVALID_PARAMETER;
    584   }
    585 
    586   //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
    587   //software breakpoint. We should send empty packet in both these cases.
    588   if ((Type == (BREAK_TYPE)DataRead) ||
    589       (Type == (BREAK_TYPE)SoftwareBreakpoint)) {
    590     return EFI_UNSUPPORTED;
    591   }
    592 
    593   //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
    594   Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
    595 
    596   if (Register == 0) {
    597     SystemContext.SystemContextIa32->Dr0 = Address;
    598     Dr7.Bits.G0 = 1;
    599     Dr7.Bits.RW0 = Type;
    600     Dr7.Bits.LEN0 = Length;
    601   } else if (Register == 1) {
    602     SystemContext.SystemContextIa32->Dr1 = Address;
    603     Dr7.Bits.G1 = 1;
    604     Dr7.Bits.RW1 = Type;
    605     Dr7.Bits.LEN1 = Length;
    606   } else if (Register == 2) {
    607     SystemContext.SystemContextIa32->Dr2 = Address;
    608     Dr7.Bits.G2 = 1;
    609     Dr7.Bits.RW2 = Type;
    610     Dr7.Bits.LEN2 = Length;
    611   } else if (Register == 3) {
    612     SystemContext.SystemContextIa32->Dr3 = Address;
    613     Dr7.Bits.G3 = 1;
    614     Dr7.Bits.RW3 = Type;
    615     Dr7.Bits.LEN3 = Length;
    616   } else {
    617     return EFI_INVALID_PARAMETER;
    618   }
    619 
    620   //Update Dr7 with appropriate Gn, RWn and LENn bits
    621   SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
    622 
    623   return EFI_SUCCESS;
    624 }
    625 
    626 
    627 /**
    628   Returns register number 0 - 3 for the maching debug register.
    629   This function compares incoming Address, Type, Length and
    630   if there is a match then it returns the appropriate register number.
    631   In case of mismatch, function returns EFI_NOT_FOUND message.
    632 
    633   @param  SystemContext  Register content at time of the exception
    634   @param  Address        Breakpoint address value
    635   @param  Length         Breakpoint length value
    636   @param  Type           Breakpoint type (Instruction, Data write,
    637                          Data read or write etc.)
    638   @param  Register       Register value to be returned
    639 
    640   @retval EFI_STATUS     Appropriate status value.
    641 
    642 **/
    643 EFI_STATUS
    644 FindMatchingDebugRegister (
    645  IN  EFI_SYSTEM_CONTEXT  SystemContext,
    646  IN  UINTN               Address,
    647  IN  UINTN               Length,
    648  IN  UINTN               Type,
    649  OUT UINTN               *Register
    650  )
    651 {
    652   IA32_DR7 Dr7;
    653 
    654   //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
    655   //software breakpoint. We should send empty packet in both these cases.
    656   if ((Type == (BREAK_TYPE)DataRead) ||
    657       (Type == (BREAK_TYPE)SoftwareBreakpoint)) {
    658     return EFI_UNSUPPORTED;
    659   }
    660 
    661   //Convert length data
    662   Length = ConvertLengthData(Length);
    663 
    664   Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
    665 
    666   if ((Dr7.Bits.G0 == 1) &&
    667       (Dr7.Bits.LEN0 == Length) &&
    668       (Dr7.Bits.RW0 == Type) &&
    669       (Address == SystemContext.SystemContextIa32->Dr0)) {
    670     *Register = 0;
    671   } else if ((Dr7.Bits.G1 == 1) &&
    672              (Dr7.Bits.LEN1 == Length) &&
    673              (Dr7.Bits.RW1 == Type) &&
    674              (Address == SystemContext.SystemContextIa32->Dr1)) {
    675     *Register = 1;
    676   } else if ((Dr7.Bits.G2 == 1) &&
    677              (Dr7.Bits.LEN2 == Length) &&
    678              (Dr7.Bits.RW2 == Type) &&
    679              (Address == SystemContext.SystemContextIa32->Dr2)) {
    680     *Register = 2;
    681   } else if ((Dr7.Bits.G3 == 1) &&
    682              (Dr7.Bits.LEN3 == Length) &&
    683              (Dr7.Bits.RW3 == Type) &&
    684              (Address == SystemContext.SystemContextIa32->Dr3)) {
    685     *Register = 3;
    686   } else {
    687     Print ((CHAR16 *)L"No match found..\n");
    688     return EFI_NOT_FOUND;
    689   }
    690 
    691   return EFI_SUCCESS;
    692 }
    693 
    694 
    695 /**
    696   Disables the particular debug register.
    697 
    698   @param  SystemContext   Register content at time of the exception
    699   @param  Register        Register to be disabled
    700 
    701   @retval EFI_STATUS      Appropriate status value.
    702 
    703 **/
    704 EFI_STATUS
    705 DisableDebugRegister (
    706  IN  EFI_SYSTEM_CONTEXT  SystemContext,
    707  IN  UINTN               Register
    708  )
    709 {
    710   IA32_DR7  Dr7;
    711   UINTN Address = 0;
    712 
    713   //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
    714   Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
    715 
    716   if (Register == 0) {
    717     SystemContext.SystemContextIa32->Dr0 = Address;
    718     Dr7.Bits.G0 = 0;
    719     Dr7.Bits.RW0 = 0;
    720     Dr7.Bits.LEN0 = 0;
    721   } else if (Register == 1) {
    722     SystemContext.SystemContextIa32->Dr1 = Address;
    723     Dr7.Bits.G1 = 0;
    724     Dr7.Bits.RW1 = 0;
    725     Dr7.Bits.LEN1 = 0;
    726   } else if (Register == 2) {
    727     SystemContext.SystemContextIa32->Dr2 = Address;
    728     Dr7.Bits.G2 = 0;
    729     Dr7.Bits.RW2 = 0;
    730     Dr7.Bits.LEN2 = 0;
    731   } else if (Register == 3) {
    732     SystemContext.SystemContextIa32->Dr3 = Address;
    733     Dr7.Bits.G3 = 0;
    734     Dr7.Bits.RW3 = 0;
    735     Dr7.Bits.LEN3 = 0;
    736   } else {
    737     return EFI_INVALID_PARAMETER;
    738   }
    739 
    740   //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
    741   SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
    742 
    743   return EFI_SUCCESS;
    744 }
    745 
    746 
    747 /**
    748   Z1, [addr], [length]
    749   Z2, [addr], [length]
    750   Z3, [addr], [length]
    751   Z4, [addr], [length]
    752 
    753   Insert hardware breakpoint/watchpoint at address addr of size length
    754 
    755   @param SystemContext  Register content at time of the exception
    756   @param *PacketData    Pointer to the Payload data for the packet
    757 
    758 **/
    759 VOID
    760 EFIAPI
    761 InsertBreakPoint (
    762   IN  EFI_SYSTEM_CONTEXT  SystemContext,
    763   IN  CHAR8              *PacketData
    764   )
    765 {
    766   UINTN Type;
    767   UINTN Address;
    768   UINTN Length;
    769   UINTN Register;
    770   EFI_STATUS Status;
    771   BREAK_TYPE BreakType = NotSupported;
    772   UINTN ErrorCode;
    773 
    774   ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
    775   if (ErrorCode > 0) {
    776     SendError ((UINT8)ErrorCode);
    777     return;
    778   }
    779 
    780   switch (Type) {
    781 
    782     case    0:   //Software breakpoint
    783       BreakType = SoftwareBreakpoint;
    784       break;
    785 
    786     case    1:   //Hardware breakpoint
    787       BreakType = InstructionExecution;
    788       break;
    789 
    790     case    2:   //Write watchpoint
    791       BreakType = DataWrite;
    792       break;
    793 
    794     case    3:   //Read watchpoint
    795       BreakType = DataRead;
    796       break;
    797 
    798     case    4:   //Access watchpoint
    799       BreakType = DataReadWrite;
    800       break;
    801 
    802     default  :
    803       Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
    804       SendError (GDB_EINVALIDBRKPOINTTYPE);
    805       return;
    806   }
    807 
    808   // Find next free debug register
    809   Status = FindNextFreeDebugRegister (SystemContext, &Register);
    810   if (EFI_ERROR(Status)) {
    811     Print ((CHAR16 *)L"No space left on device\n");
    812     SendError (GDB_ENOSPACE);
    813     return;
    814   }
    815 
    816   // Write Address, length data at particular DR register
    817   Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
    818   if (EFI_ERROR(Status)) {
    819     if (Status == EFI_UNSUPPORTED) {
    820       SendNotSupported();
    821       return;
    822     }
    823 
    824     SendError (GDB_EINVALIDARG);
    825     return;
    826   }
    827 
    828   SendSuccess ();
    829 }
    830 
    831 
    832 /**
    833   z1, [addr], [length]
    834   z2, [addr], [length]
    835   z3, [addr], [length]
    836   z4, [addr], [length]
    837 
    838   Remove hardware breakpoint/watchpoint at address addr of size length
    839 
    840   @param *PacketData    Pointer to the Payload data for the packet
    841 
    842 **/
    843 VOID
    844 EFIAPI
    845 RemoveBreakPoint (
    846   IN  EFI_SYSTEM_CONTEXT  SystemContext,
    847   IN  CHAR8               *PacketData
    848   )
    849 {
    850   UINTN      Type;
    851   UINTN      Address;
    852   UINTN      Length;
    853   UINTN      Register;
    854   BREAK_TYPE BreakType = NotSupported;
    855   EFI_STATUS Status;
    856   UINTN      ErrorCode;
    857 
    858   //Parse breakpoint packet data
    859   ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
    860   if (ErrorCode > 0) {
    861     SendError ((UINT8)ErrorCode);
    862     return;
    863   }
    864 
    865   switch (Type) {
    866 
    867     case    0:   //Software breakpoint
    868       BreakType = SoftwareBreakpoint;
    869       break;
    870 
    871     case    1:   //Hardware breakpoint
    872       BreakType = InstructionExecution;
    873       break;
    874 
    875     case    2:   //Write watchpoint
    876       BreakType = DataWrite;
    877       break;
    878 
    879     case    3:   //Read watchpoint
    880       BreakType = DataRead;
    881       break;
    882 
    883     case    4:   //Access watchpoint
    884       BreakType = DataReadWrite;
    885       break;
    886 
    887     default  :
    888       SendError (GDB_EINVALIDBRKPOINTTYPE);
    889       return;
    890   }
    891 
    892   //Find matching debug register
    893   Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
    894   if (EFI_ERROR(Status)) {
    895     if (Status == EFI_UNSUPPORTED) {
    896       SendNotSupported();
    897       return;
    898     }
    899 
    900     SendError (GDB_ENOSPACE);
    901     return;
    902   }
    903 
    904   //Remove breakpoint
    905   Status = DisableDebugRegister(SystemContext, Register);
    906   if (EFI_ERROR(Status)) {
    907     SendError (GDB_EINVALIDARG);
    908     return;
    909   }
    910 
    911   SendSuccess ();
    912 }
    913 
    914 
    915 /**
    916   Initialize debug agent.
    917 
    918   This function is used to set up debug environment to support source level debugging.
    919   If certain Debug Agent Library instance has to save some private data in the stack,
    920   this function must work on the mode that doesn't return to the caller, then
    921   the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
    922   function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
    923   responsible to invoke the passing-in function at the end of InitializeDebugAgent().
    924 
    925   If the parameter Function is not NULL, Debug Agent Library instance will invoke it by
    926   passing in the Context to be its parameter.
    927 
    928   If Function() is NULL, Debug Agent Library instance will return after setup debug
    929   environment.
    930 
    931   @param[in] InitFlag     Init flag is used to decide the initialize process.
    932   @param[in] Context      Context needed according to InitFlag; it was optional.
    933   @param[in] Function     Continue function called by debug agent library; it was
    934                           optional.
    935 
    936 **/
    937 VOID
    938 EFIAPI
    939 InitializeDebugAgent (
    940   IN UINT32                InitFlag,
    941   IN VOID                  *Context, OPTIONAL
    942   IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL
    943   )
    944 {
    945   // BugBug: Add the code to build an GDT/IDT
    946 
    947   if (Function != NULL) {
    948     Function (Context);
    949   }
    950 }
    951 
    952