@ -1,682 +0,0 @@
 
		
	
		
			
				/** @file  
		
	
		
			
				  Processor specific parts of the GDB stub  
		
	
		
			
				 
		
	
		
			
				  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>  
		
	
		
			
				 
		
	
		
			
				  SPDX-License-Identifier: BSD-2-Clause-Patent  
		
	
		
			
				 
		
	
		
			
				**/  
		
	
		
			
				 
		
	
		
			
				# include  <GdbStubInternal.h>  
		
	
		
			
				# include  <Library/CacheMaintenanceLib.h>  
		
	
		
			
				# include  <Library/PrintLib.h>  
		
	
		
			
				 
		
	
		
			
				//  
		
	
		
			
				// Array of exception types that need to be hooked by the debugger  
		
	
		
			
				// (efi, gdb) //efi number  
		
	
		
			
				//  
		
	
		
			
				EFI_EXCEPTION_TYPE_ENTRY   gExceptionType [ ]  =  {  
		
	
		
			
				  {  EXCEPT_ARM_SOFTWARE_INTERRUPT ,  GDB_SIGTRAP  } 
 
		
	
		
			
				  //  { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP }, 
 
		
	
		
			
				//  { EXCEPT_ARM_PREFETCH_ABORT,        GDB_SIGTRAP },  
		
	
		
			
				//  { EXCEPT_ARM_DATA_ABORT,            GDB_SIGEMT  },  
		
	
		
			
				//  { EXCEPT_ARM_RESERVED,              GDB_SIGILL  }  
		
	
		
			
				} ;  
		
	
		
			
				 
		
	
		
			
				UINTN   gRegisterOffsets [ ]  =  {  
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R0 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R1 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R2 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R3 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R4 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R5 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R6 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R7 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R8 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R9 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R10 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R11 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  R12 ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  SP ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  LR ) , 
 
		
	
		
			
				  OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  PC ) , 
 
		
	
		
			
				  0x00000F01 ,                         // f0 
 
		
	
		
			
				0x00000F02 ,  
		
	
		
			
				  0x00000F03 , 
 
		
	
		
			
				  0x00000F11 ,                         // f1 
 
		
	
		
			
				0x00000F12 ,  
		
	
		
			
				  0x00000F13 , 
 
		
	
		
			
				  0x00000F21 ,                         // f2 
 
		
	
		
			
				0x00000F22 ,  
		
	
		
			
				  0x00000F23 , 
 
		
	
		
			
				  0x00000F31 ,                         // f3 
 
		
	
		
			
				0x00000F32 ,  
		
	
		
			
				  0x00000F33 , 
 
		
	
		
			
				  0x00000F41 ,                         // f4 
 
		
	
		
			
				0x00000F42 ,  
		
	
		
			
				  0x00000F43 , 
 
		
	
		
			
				  0x00000F51 ,                         // f5 
 
		
	
		
			
				0x00000F52 ,  
		
	
		
			
				  0x00000F53 , 
 
		
	
		
			
				  0x00000F61 ,                         // f6 
 
		
	
		
			
				0x00000F62 ,  
		
	
		
			
				  0x00000F63 , 
 
		
	
		
			
				  0x00000F71 ,                         // f7 
 
		
	
		
			
				0x00000F72 ,  
		
	
		
			
				  0x00000F73 , 
 
		
	
		
			
				  0x00000FFF ,                         // fps 
 
		
	
		
			
				OFFSET_OF  ( EFI_SYSTEM_CONTEXT_ARM ,  CPSR )  
		
	
		
			
				} ;  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Return the number of entries in the gExceptionType[]  
		
	
		
			
				 
		
	
		
			
				 @retval  UINTN, the number of entries in the gExceptionType[] array.  
		
	
		
			
				 **/  
		
	
		
			
				UINTN  
		
	
		
			
				MaxEfiException  (  
		
	
		
			
				  VOID 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  return  sizeof  ( gExceptionType )  /  sizeof  ( EFI_EXCEPTION_TYPE_ENTRY ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Return the number of entries in the gRegisters[]  
		
	
		
			
				 
		
	
		
			
				 @retval  UINTN, the number of entries (registers) in the gRegisters[] array.  
		
	
		
			
				 **/  
		
	
		
			
				UINTN  
		
	
		
			
				MaxRegisterCount  (  
		
	
		
			
				  VOID 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  return  sizeof  ( gRegisterOffsets )  /  sizeof  ( UINTN ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Check to see if the ISA is supported.  
		
	
		
			
				 ISA = Instruction Set Architecture  
		
	
		
			
				 
		
	
		
			
				 @retval TRUE if Isa is supported  
		
	
		
			
				 
		
	
		
			
				**/  
		
	
		
			
				BOOLEAN  
		
	
		
			
				CheckIsa  (  
		
	
		
			
				  IN   EFI_INSTRUCTION_SET_ARCHITECTURE   Isa 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  if  ( Isa  = =  IsaArm )  { 
 
		
	
		
			
				    return  TRUE ; 
 
		
	
		
			
				  }  else  { 
 
		
	
		
			
				    return  FALSE ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering  
		
	
		
			
				 It is, by default, set to find the register pointer of the ARM member  
		
	
		
			
				 @param   SystemContext     Register content at time of the exception  
		
	
		
			
				 @param   RegNumber       The register to which we want to find a pointer  
		
	
		
			
				 @retval  the pointer to the RegNumber-th pointer  
		
	
		
			
				 **/  
		
	
		
			
				UINTN  *  
		
	
		
			
				FindPointerToRegister  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   UINTN                RegNumber 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINT8   * TempPtr ; 
 
		
	
		
			
				 
		
	
		
			
				  ASSERT  ( gRegisterOffsets [ RegNumber ]  <  0xF00 ) ; 
 
		
	
		
			
				  TempPtr  =  ( ( UINT8  * ) SystemContext . SystemContextArm )  +  gRegisterOffsets [ RegNumber ] ; 
 
		
	
		
			
				  return  ( UINT32  * ) TempPtr ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr  
		
	
		
			
				 @param SystemContext     Register content at time of the exception  
		
	
		
			
				 @param   RegNumber       the number of the register that we want to read  
		
	
		
			
				 @param   OutBufPtr       pointer to the output buffer's end. the new data will be added from this point on.  
		
	
		
			
				 @retval  the pointer to the next character of the output buffer that is available to be written on.  
		
	
		
			
				 **/  
		
	
		
			
				CHAR8  *  
		
	
		
			
				BasicReadRegister  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   UINTN                RegNumber , 
 
		
	
		
			
				  IN   CHAR8                * OutBufPtr 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN   RegSize ; 
 
		
	
		
			
				  CHAR8   Char ; 
 
		
	
		
			
				 
		
	
		
			
				  if  ( gRegisterOffsets [ RegNumber ]  >  0xF00 )  { 
 
		
	
		
			
				    AsciiSPrint  ( OutBufPtr ,  9 ,  " 00000000 " ) ; 
 
		
	
		
			
				    OutBufPtr  + =  8 ; 
 
		
	
		
			
				    return  OutBufPtr ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  RegSize  =  0 ; 
 
		
	
		
			
				  while  ( RegSize  <  32 )  { 
 
		
	
		
			
				    Char  =  mHexToStr [ ( UINT8 ) ( ( * FindPointerToRegister  ( SystemContext ,  RegNumber )  > >  ( RegSize + 4 ) )  &  0xf ) ] ; 
 
		
	
		
			
				    if  ( ( Char  > =  ' A ' )  & &  ( Char  < =  ' F ' ) )  { 
 
		
	
		
			
				      Char  =  Char  -  ' A '  +  ' a ' ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				 
		
	
		
			
				    * OutBufPtr + +  =  Char ; 
 
		
	
		
			
				 
		
	
		
			
				    Char  =  mHexToStr [ ( UINT8 ) ( ( * FindPointerToRegister  ( SystemContext ,  RegNumber )  > >  RegSize )  &  0xf ) ] ; 
 
		
	
		
			
				    if  ( ( Char  > =  ' A ' )  & &  ( Char  < =  ' F ' ) )  { 
 
		
	
		
			
				      Char  =  Char  -  ' A '  +  ' a ' ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				 
		
	
		
			
				    * OutBufPtr + +  =  Char ; 
 
		
	
		
			
				 
		
	
		
			
				    RegSize  =  RegSize  +  8 ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  return  OutBufPtr ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 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      Pointer to the input buffer received from gdb server  
		
	
		
			
				 **/  
		
	
		
			
				VOID  
		
	
		
			
				ReadNthRegister  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   CHAR8                * InBuffer 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN   RegNumber ; 
 
		
	
		
			
				  CHAR8   OutBuffer [ 9 ] ;  // 1 reg=8 hex chars, and the end '\0' (escape seq) 
 
		
	
		
			
				CHAR8   * OutBufPtr ;    // pointer to the output buffer  
		
	
		
			
				 
		
	
		
			
				  RegNumber  =  AsciiStrHexToUintn  ( & InBuffer [ 1 ] ) ; 
 
		
	
		
			
				 
		
	
		
			
				  if  ( RegNumber  > =  MaxRegisterCount  ( ) )  { 
 
		
	
		
			
				    SendError  ( GDB_EINVALIDREGNUM ) ; 
 
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  OutBufPtr  =  OutBuffer ; 
 
		
	
		
			
				  OutBufPtr  =  BasicReadRegister  ( SystemContext ,  RegNumber ,  OutBufPtr ) ; 
 
		
	
		
			
				 
		
	
		
			
				  * OutBufPtr  =  ' \0 ' ;   // the end of the buffer 
 
		
	
		
			
				SendPacket  ( OutBuffer ) ;  
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Reads the general registers into an output buffer  and sends it as a packet  
		
	
		
			
				 @param   SystemContext     Register content at time of the exception  
		
	
		
			
				 **/  
		
	
		
			
				VOID  
		
	
		
			
				EFIAPI  
		
	
		
			
				ReadGeneralRegisters  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN   Index ; 
 
		
	
		
			
				  CHAR8   * OutBuffer ; 
 
		
	
		
			
				  CHAR8   * OutBufPtr ; 
 
		
	
		
			
				  UINTN   RegisterCount  =  MaxRegisterCount  ( ) ; 
 
		
	
		
			
				 
		
	
		
			
				  // It is not safe to allocate pool here.... 
 
		
	
		
			
				OutBuffer  =  AllocatePool  ( ( RegisterCount  *  8 )  +  1 ) ;  // 8 bytes per register in string format plus a null to terminate  
		
	
		
			
				OutBufPtr  =  OutBuffer ;  
		
	
		
			
				  for  ( Index  =  0 ;  Index  <  RegisterCount ;  Index + + )  { 
 
		
	
		
			
				    OutBufPtr  =  BasicReadRegister  ( SystemContext ,  Index ,  OutBufPtr ) ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  * OutBufPtr  =  ' \0 ' ; 
 
		
	
		
			
				  SendPacket  ( OutBuffer ) ; 
 
		
	
		
			
				  FreePool  ( OutBuffer ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr  
		
	
		
			
				 @param   SystemContext       Register content at time of the exception  
		
	
		
			
				 @param   RegNumber         the number of the register that we want to write  
		
	
		
			
				 @param   InBufPtr          pointer to the output buffer. the new data will be extracted from the input buffer from this point on.  
		
	
		
			
				 @retval  the pointer to the next character of the input buffer that can be used  
		
	
		
			
				 **/  
		
	
		
			
				CHAR8  
		
	
		
			
				*  
		
	
		
			
				BasicWriteRegister  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   UINTN                RegNumber , 
 
		
	
		
			
				  IN   CHAR8                * InBufPtr 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN    RegSize ; 
 
		
	
		
			
				  UINTN    TempValue ;  // the value transferred from a hex char 
 
		
	
		
			
				UINT32   NewValue ;   // the new value of the RegNumber-th Register  
		
	
		
			
				 
		
	
		
			
				  if  ( gRegisterOffsets [ RegNumber ]  >  0xF00 )  { 
 
		
	
		
			
				    return  InBufPtr  +  8 ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  NewValue  =  0 ; 
 
		
	
		
			
				  RegSize   =  0 ; 
 
		
	
		
			
				  while  ( RegSize  <  32 )  { 
 
		
	
		
			
				    TempValue  =  HexCharToInt  ( * InBufPtr + + ) ; 
 
		
	
		
			
				 
		
	
		
			
				    if  ( ( INTN ) TempValue  <  0 )  { 
 
		
	
		
			
				      SendError  ( GDB_EBADMEMDATA ) ; 
 
		
	
		
			
				      return  NULL ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				 
		
	
		
			
				    NewValue  + =  ( TempValue  < <  ( RegSize + 4 ) ) ; 
 
		
	
		
			
				    TempValue  =  HexCharToInt  ( * InBufPtr + + ) ; 
 
		
	
		
			
				 
		
	
		
			
				    if  ( ( INTN ) TempValue  <  0 )  { 
 
		
	
		
			
				      SendError  ( GDB_EBADMEMDATA ) ; 
 
		
	
		
			
				      return  NULL ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				 
		
	
		
			
				    NewValue  + =  ( TempValue  < <  RegSize ) ; 
 
		
	
		
			
				    RegSize    =  RegSize  +  8 ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  * ( FindPointerToRegister  ( SystemContext ,  RegNumber ) )  =  NewValue ; 
 
		
	
		
			
				  return  InBufPtr ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/** ‘ ’   
		
	
		
			
				 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      Pointer to the input buffer received from gdb server  
		
	
		
			
				 **/  
		
	
		
			
				VOID  
		
	
		
			
				WriteNthRegister  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   CHAR8                * InBuffer 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN   RegNumber ; 
 
		
	
		
			
				  CHAR8   RegNumBuffer [ MAX_REG_NUM_BUF_SIZE ] ;  // put the 'n..' part of the message into this array 
 
		
	
		
			
				CHAR8   * RegNumBufPtr ;  
		
	
		
			
				  CHAR8   * InBufPtr ;  // pointer to the input buffer 
 
		
	
		
			
				 
		
	
		
			
				  // find the register number to write 
 
		
	
		
			
				InBufPtr      =  & InBuffer [ 1 ] ;  
		
	
		
			
				  RegNumBufPtr  =  RegNumBuffer ; 
 
		
	
		
			
				  while  ( * InBufPtr  ! =  ' = ' )  { 
 
		
	
		
			
				    * RegNumBufPtr + +  =  * InBufPtr + + ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  * RegNumBufPtr  =  ' \0 ' ; 
 
		
	
		
			
				  RegNumber      =  AsciiStrHexToUintn  ( RegNumBuffer ) ; 
 
		
	
		
			
				 
		
	
		
			
				  // check if this is a valid Register Number 
 
		
	
		
			
				if  ( RegNumber  > =  MaxRegisterCount  ( ) )  {  
		
	
		
			
				    SendError  ( GDB_EINVALIDREGNUM ) ; 
 
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  InBufPtr + + ;   // skips the '=' character 
 
		
	
		
			
				BasicWriteRegister  ( SystemContext ,  RegNumber ,  InBufPtr ) ;  
		
	
		
			
				  SendSuccess  ( ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/** ‘ ’   
		
	
		
			
				 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  
		
	
		
			
				EFIAPI  
		
	
		
			
				WriteGeneralRegisters  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   CHAR8                * InBuffer 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN   i ; 
 
		
	
		
			
				  CHAR8   * InBufPtr ;  /// pointer to the input buffer 
 
		
	
		
			
				UINTN   MinLength ;  
		
	
		
			
				  UINTN   RegisterCount  =  MaxRegisterCount  ( ) ; 
 
		
	
		
			
				 
		
	
		
			
				  MinLength  =  ( RegisterCount  *  8 )  +  1 ;   // 'G' plus the registers in ASCII format 
 
		
	
		
			
				 
		
	
		
			
				  if  ( AsciiStrLen  ( InBuffer )  <  MinLength )  { 
 
		
	
		
			
				    // Bad message. Message is not the right length 
 
		
	
		
			
				SendError  ( GDB_EBADBUFSIZE ) ;  
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  InBufPtr  =  & InBuffer [ 1 ] ; 
 
		
	
		
			
				 
		
	
		
			
				  // Read the new values for the registers from the input buffer to an array, NewValueArray. 
 
		
	
		
			
				// The values in the array are in the gdb ordering  
		
	
		
			
				for  ( i  =  0 ;  i  <  RegisterCount ;  i + + )  {  
		
	
		
			
				    InBufPtr  =  BasicWriteRegister  ( SystemContext ,  i ,  InBufPtr ) ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  SendSuccess  ( ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				// What about Thumb?  
		
	
		
			
				// Use SWI 0xdbdbdb as the debug instruction  
		
	
		
			
				# define GDB_ARM_BKPT  0xefdbdbdb  
		
	
		
			
				 
		
	
		
			
				BOOLEAN   mSingleStepActive  =  FALSE ;  
		
	
		
			
				UINT32    mSingleStepPC ;  
		
	
		
			
				UINT32    mSingleStepData ;  
		
	
		
			
				UINTN     mSingleStepDataSize ;  
		
	
		
			
				 
		
	
		
			
				typedef  struct  {  
		
	
		
			
				  LIST_ENTRY     Link ; 
 
		
	
		
			
				  UINT64         Signature ; 
 
		
	
		
			
				  UINT32         Address ; 
 
		
	
		
			
				  UINT32         Instruction ; 
 
		
	
		
			
				}  ARM_SOFTWARE_BREAKPOINT ;  
		
	
		
			
				 
		
	
		
			
				# define ARM_SOFTWARE_BREAKPOINT_SIGNATURE  SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T')  
		
	
		
			
				# define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a)  CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE)  
		
	
		
			
				 
		
	
		
			
				LIST_ENTRY   BreakpointList ;  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Insert Single Step in the SystemContext  
		
	
		
			
				 
		
	
		
			
				 @param SystemContext  Register content at time of the exception  
		
	
		
			
				 **/  
		
	
		
			
				VOID  
		
	
		
			
				AddSingleStep  (  
		
	
		
			
				  IN  EFI_SYSTEM_CONTEXT   SystemContext 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  if  ( mSingleStepActive )  { 
 
		
	
		
			
				    // Currently don't support nesting 
 
		
	
		
			
				return ;  
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  mSingleStepActive  =  TRUE ; 
 
		
	
		
			
				 
		
	
		
			
				  mSingleStepPC  =  SystemContext . SystemContextArm - > PC ; 
 
		
	
		
			
				 
		
	
		
			
				  mSingleStepDataSize       =  sizeof  ( UINT32 ) ; 
 
		
	
		
			
				  mSingleStepData           =  ( * ( UINT32  * ) mSingleStepPC ) ; 
 
		
	
		
			
				  * ( UINT32  * ) mSingleStepPC  =  GDB_ARM_BKPT ; 
 
		
	
		
			
				  if  ( * ( UINT32  * ) mSingleStepPC  ! =  GDB_ARM_BKPT )  { 
 
		
	
		
			
				    // For some reason our breakpoint did not take 
 
		
	
		
			
				mSingleStepActive  =  FALSE ;  
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  InvalidateInstructionCacheRange  ( ( VOID  * ) mSingleStepPC ,  mSingleStepDataSize ) ; 
 
		
	
		
			
				  // DEBUG((DEBUG_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC)); 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Remove Single Step in the SystemContext  
		
	
		
			
				 
		
	
		
			
				 @param SystemContext  Register content at time of the exception  
		
	
		
			
				 **/  
		
	
		
			
				VOID  
		
	
		
			
				RemoveSingleStep  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  if  ( ! mSingleStepActive )  { 
 
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  if  ( mSingleStepDataSize  = =  sizeof  ( UINT16 ) )  { 
 
		
	
		
			
				    * ( UINT16  * ) mSingleStepPC  =  ( UINT16 ) mSingleStepData ; 
 
		
	
		
			
				  }  else  { 
 
		
	
		
			
				    // DEBUG((DEBUG_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData)); 
 
		
	
		
			
				* ( UINT32  * ) mSingleStepPC  =  mSingleStepData ;  
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  InvalidateInstructionCacheRange  ( ( VOID  * ) mSingleStepPC ,  mSingleStepDataSize ) ; 
 
		
	
		
			
				  mSingleStepActive  =  FALSE ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/**  
		
	
		
			
				 Continue. addr is Address to resume. If addr is omitted, resume at current  
		
	
		
			
				 Address.  
		
	
		
			
				 
		
	
		
			
				 @param   SystemContext     Register content at time of the exception  
		
	
		
			
				 **/  
		
	
		
			
				VOID  
		
	
		
			
				EFIAPI  
		
	
		
			
				ContinueAtAddress  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN     CHAR8              * PacketData 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  if  ( PacketData [ 1 ]  ! =  ' \0 ' )  { 
 
		
	
		
			
				    SystemContext . SystemContextArm - > PC  =  AsciiStrHexToUintn  ( & PacketData [ 1 ] ) ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				/** ‘ ’   
		
	
		
			
				 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  
		
	
		
			
				 **/  
		
	
		
			
				VOID  
		
	
		
			
				EFIAPI  
		
	
		
			
				SingleStep  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN     CHAR8              * PacketData 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  SendNotSupported  ( ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				UINTN  
		
	
		
			
				GetBreakpointDataAddress  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   UINTN                BreakpointNumber 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  return  0 ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				UINTN  
		
	
		
			
				GetBreakpointDetected  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  return  0 ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				BREAK_TYPE  
		
	
		
			
				GetBreakpointType  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   UINTN                BreakpointNumber 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  return  NotSupported ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				ARM_SOFTWARE_BREAKPOINT  *  
		
	
		
			
				SearchBreakpointList  (  
		
	
		
			
				  IN   UINT32   Address 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  LIST_ENTRY                * Current ; 
 
		
	
		
			
				  ARM_SOFTWARE_BREAKPOINT   * Breakpoint ; 
 
		
	
		
			
				 
		
	
		
			
				  Current  =  GetFirstNode  ( & BreakpointList ) ; 
 
		
	
		
			
				  while  ( ! IsNull  ( & BreakpointList ,  Current ) )  { 
 
		
	
		
			
				    Breakpoint  =  ARM_SOFTWARE_BREAKPOINT_FROM_LINK  ( Current ) ; 
 
		
	
		
			
				 
		
	
		
			
				    if  ( Address  = =  Breakpoint - > Address )  { 
 
		
	
		
			
				      return  Breakpoint ; 
 
		
	
		
			
				    } 
 
		
	
		
			
				 
		
	
		
			
				    Current  =  GetNextNode  ( & BreakpointList ,  Current ) ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  return  NULL ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				VOID  
		
	
		
			
				SetBreakpoint  (  
		
	
		
			
				  IN  UINT32   Address 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  ARM_SOFTWARE_BREAKPOINT   * Breakpoint ; 
 
		
	
		
			
				 
		
	
		
			
				  Breakpoint  =  SearchBreakpointList  ( Address ) ; 
 
		
	
		
			
				 
		
	
		
			
				  if  ( Breakpoint  ! =  NULL )  { 
 
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  // create and fill breakpoint structure 
 
		
	
		
			
				Breakpoint  =  AllocatePool  ( sizeof  ( ARM_SOFTWARE_BREAKPOINT ) ) ;  
		
	
		
			
				 
		
	
		
			
				  Breakpoint - > Signature    =  ARM_SOFTWARE_BREAKPOINT_SIGNATURE ; 
 
		
	
		
			
				  Breakpoint - > Address      =  Address ; 
 
		
	
		
			
				  Breakpoint - > Instruction  =  * ( UINT32  * ) Address ; 
 
		
	
		
			
				 
		
	
		
			
				  // Add it to the list 
 
		
	
		
			
				InsertTailList  ( & BreakpointList ,  & Breakpoint - > Link ) ;  
		
	
		
			
				 
		
	
		
			
				  // Insert the software breakpoint 
 
		
	
		
			
				* ( UINT32  * ) Address  =  GDB_ARM_BKPT ;  
		
	
		
			
				  InvalidateInstructionCacheRange  ( ( VOID  * ) Address ,  4 ) ; 
 
		
	
		
			
				 
		
	
		
			
				  // DEBUG((DEBUG_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address)); 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				VOID  
		
	
		
			
				ClearBreakpoint  (  
		
	
		
			
				  IN  UINT32   Address 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  ARM_SOFTWARE_BREAKPOINT   * Breakpoint ; 
 
		
	
		
			
				 
		
	
		
			
				  Breakpoint  =  SearchBreakpointList  ( Address ) ; 
 
		
	
		
			
				 
		
	
		
			
				  if  ( Breakpoint  = =  NULL )  { 
 
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  // Add it to the list 
 
		
	
		
			
				RemoveEntryList  ( & Breakpoint - > Link ) ;  
		
	
		
			
				 
		
	
		
			
				  // Restore the original instruction 
 
		
	
		
			
				* ( UINT32  * ) Address  =  Breakpoint - > Instruction ;  
		
	
		
			
				  InvalidateInstructionCacheRange  ( ( VOID  * ) Address ,  4 ) ; 
 
		
	
		
			
				 
		
	
		
			
				  // DEBUG((DEBUG_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address)); 
 
		
	
		
			
				 
		
	
		
			
				  FreePool  ( Breakpoint ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				VOID  
		
	
		
			
				EFIAPI  
		
	
		
			
				InsertBreakPoint  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   CHAR8                * PacketData 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN   Type ; 
 
		
	
		
			
				  UINTN   Address ; 
 
		
	
		
			
				  UINTN   Length ; 
 
		
	
		
			
				  UINTN   ErrorCode ; 
 
		
	
		
			
				 
		
	
		
			
				  ErrorCode  =  ParseBreakpointPacket  ( PacketData ,  & Type ,  & Address ,  & Length ) ; 
 
		
	
		
			
				  if  ( ErrorCode  >  0 )  { 
 
		
	
		
			
				    SendError  ( ( UINT8 ) ErrorCode ) ; 
 
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  switch  ( Type )  { 
 
		
	
		
			
				    case  0 :    // Software breakpoint 
 
		
	
		
			
				break ;  
		
	
		
			
				 
		
	
		
			
				    default : 
 
		
	
		
			
				      DEBUG  ( ( DEBUG_ERROR ,  " Insert breakpoint default: %x \n " ,  Type ) ) ; 
 
		
	
		
			
				      SendError  ( GDB_EINVALIDBRKPOINTTYPE ) ; 
 
		
	
		
			
				      return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  SetBreakpoint  ( Address ) ; 
 
		
	
		
			
				 
		
	
		
			
				  SendSuccess  ( ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				VOID  
		
	
		
			
				EFIAPI  
		
	
		
			
				RemoveBreakPoint  (  
		
	
		
			
				  IN   EFI_SYSTEM_CONTEXT   SystemContext , 
 
		
	
		
			
				  IN   CHAR8                * PacketData 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINTN   Type ; 
 
		
	
		
			
				  UINTN   Address ; 
 
		
	
		
			
				  UINTN   Length ; 
 
		
	
		
			
				  UINTN   ErrorCode ; 
 
		
	
		
			
				 
		
	
		
			
				  // Parse breakpoint packet data 
 
		
	
		
			
				ErrorCode  =  ParseBreakpointPacket  ( PacketData ,  & Type ,  & Address ,  & Length ) ;  
		
	
		
			
				  if  ( ErrorCode  >  0 )  { 
 
		
	
		
			
				    SendError  ( ( UINT8 ) ErrorCode ) ; 
 
		
	
		
			
				    return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  switch  ( Type )  { 
 
		
	
		
			
				    case  0 :    // Software breakpoint 
 
		
	
		
			
				break ;  
		
	
		
			
				 
		
	
		
			
				    default : 
 
		
	
		
			
				      SendError  ( GDB_EINVALIDBRKPOINTTYPE ) ; 
 
		
	
		
			
				      return ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  ClearBreakpoint  ( Address ) ; 
 
		
	
		
			
				 
		
	
		
			
				  SendSuccess  ( ) ; 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				VOID  
		
	
		
			
				InitializeProcessor  (  
		
	
		
			
				  VOID 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  // Initialize breakpoint list 
 
		
	
		
			
				InitializeListHead  ( & BreakpointList ) ;  
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				BOOLEAN  
		
	
		
			
				ValidateAddress  (  
		
	
		
			
				  IN   VOID   * Address 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  if  ( ( UINT32 ) Address  <  0x80000000 )  { 
 
		
	
		
			
				    return  FALSE ; 
 
		
	
		
			
				  }  else  { 
 
		
	
		
			
				    return  TRUE ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				}  
		
	
		
			
				 
		
	
		
			
				BOOLEAN  
		
	
		
			
				ValidateException  (  
		
	
		
			
				  IN   EFI_EXCEPTION_TYPE      ExceptionType , 
 
		
	
		
			
				  IN  OUT  EFI_SYSTEM_CONTEXT   SystemContext 
 
		
	
		
			
				  ) 
 
		
	
		
			
				{  
		
	
		
			
				  UINT32   ExceptionAddress ; 
 
		
	
		
			
				  UINT32   Instruction ; 
 
		
	
		
			
				 
		
	
		
			
				  // Is it a debugger SWI? 
 
		
	
		
			
				ExceptionAddress  =  SystemContext . SystemContextArm - > PC  - =  4 ;  
		
	
		
			
				  Instruction       =  * ( UINT32  * ) ExceptionAddress ; 
 
		
	
		
			
				  if  ( Instruction  ! =  GDB_ARM_BKPT )  { 
 
		
	
		
			
				    return  FALSE ; 
 
		
	
		
			
				  } 
 
		
	
		
			
				 
		
	
		
			
				  // Special for SWI-based exception handling.  SWI sets up the context 
 
		
	
		
			
				// to return to the instruction following the SWI instruction - NOT what we want  
		
	
		
			
				// for a debugger!  
		
	
		
			
				SystemContext . SystemContextArm - > PC  =  ExceptionAddress ;  
		
	
		
			
				 
		
	
		
			
				  return  TRUE ; 
 
		
	
		
			
				}