git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10870 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1201 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1201 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Commond Debug Agent library implementition. It mainly includes
 | 
						|
  the first C function called by exception/interrupt handlers,
 | 
						|
  read/write debug packet to communication with HOST based on transfer
 | 
						|
  protocol.
 | 
						|
 | 
						|
  Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
 | 
						|
  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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "DebugAgent.h"
 | 
						|
#include "Ia32/DebugException.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Check if HOST is connected based on Mailbox.
 | 
						|
 | 
						|
  @retval TRUE        HOST is connected.
 | 
						|
  @retval FALSE       HOST is not connected.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsHostConnected (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_AGENT_MAILBOX          *Mailbox;
 | 
						|
 | 
						|
  Mailbox = GetMailboxPointer ();
 | 
						|
 | 
						|
  if (Mailbox->DebugFlag.Bits.HostPresent == 1) {
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set HOST connect flag in Mailbox.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetHostConnectedFlag (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_AGENT_MAILBOX          *Mailbox;
 | 
						|
 | 
						|
  Mailbox = GetMailboxPointer ();
 | 
						|
 | 
						|
  Mailbox->DebugFlag.Bits.HostPresent = 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set debug flag of Debug Agent in Mailbox.
 | 
						|
 | 
						|
  @param DebugFlag       Debug Flag defined by transfer protocol.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetDebugFlag (
 | 
						|
  IN UINT32               DebugFlag
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_AGENT_MAILBOX          *Mailbox;
 | 
						|
 | 
						|
  Mailbox = GetMailboxPointer ();
 | 
						|
 | 
						|
  if ((DebugFlag & SOFT_DEBUGGER_SETTING_SMM_ENTRY_BREAK) != 0) {
 | 
						|
    Mailbox->DebugFlag.Bits.BreakOnNextSmi = 1;
 | 
						|
  } else {
 | 
						|
    Mailbox->DebugFlag.Bits.BreakOnNextSmi = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Exectue GO command.
 | 
						|
 | 
						|
  @param[in] CpuContext        Pointer to saved CPU context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CommandGo (
 | 
						|
  IN DEBUG_CPU_CONTEXT         *CpuContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  IA32_EFLAGS32                *Eflags;
 | 
						|
 | 
						|
  Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
 | 
						|
  Eflags->Bits.TF = 0;
 | 
						|
  Eflags->Bits.RF = 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Exectue Stepping command.
 | 
						|
 | 
						|
  @param[in] CpuContext        Pointer to saved CPU context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CommandStepping (
 | 
						|
  IN DEBUG_CPU_CONTEXT          *CpuContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  IA32_EFLAGS32                *Eflags;
 | 
						|
 | 
						|
  Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
 | 
						|
  Eflags->Bits.TF = 1;
 | 
						|
  Eflags->Bits.RF = 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set debug register for hardware breakpoint.
 | 
						|
 | 
						|
  @param[in] CpuContext      Pointer to saved CPU context.
 | 
						|
  @param[in] SetHwBreakpoint Hardware breakpoint to be set.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SetDebugRegister (
 | 
						|
  IN DEBUG_CPU_CONTEXT             *CpuContext,
 | 
						|
  IN DEBUG_DATA_SET_HW_BREAKPOINT  *SetHwBreakpoint
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                      RegisterIndex;
 | 
						|
  UINTN                      Dr7Value;
 | 
						|
 | 
						|
  RegisterIndex = SetHwBreakpoint->Type.Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set debug address
 | 
						|
  //
 | 
						|
  * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;
 | 
						|
 | 
						|
  Dr7Value = CpuContext->Dr7;
 | 
						|
 | 
						|
  //
 | 
						|
  // Enable Gx, Lx
 | 
						|
  //
 | 
						|
  Dr7Value |= 0x3 << (RegisterIndex * 2);
 | 
						|
  //
 | 
						|
  // Set RWx and Lenx
 | 
						|
  //
 | 
						|
  Dr7Value &= ~(0xf0000 << (RegisterIndex * 4));
 | 
						|
  Dr7Value |= (SetHwBreakpoint->Type.Length | SetHwBreakpoint->Type.Access) << (RegisterIndex * 4);
 | 
						|
  //
 | 
						|
  // Enable GE, LE
 | 
						|
  //
 | 
						|
  Dr7Value |= 0x300;
 | 
						|
 | 
						|
  CpuContext->Dr7 = Dr7Value;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clear debug register for hardware breakpoint.
 | 
						|
 | 
						|
  @param[in] CpuContext        Pointer to saved CPU context.
 | 
						|
  @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
ClearDebugRegister (
 | 
						|
  IN DEBUG_CPU_CONTEXT                 *CpuContext,
 | 
						|
  IN DEBUG_DATA_CLEAR_HW_BREAKPOINT    *ClearHwBreakpoint
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {
 | 
						|
    CpuContext->Dr0 = 0;
 | 
						|
    CpuContext->Dr7 &= ~(0x3 << 0);
 | 
						|
  }
 | 
						|
  if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {
 | 
						|
    CpuContext->Dr1 = 0;
 | 
						|
    CpuContext->Dr7 &= ~(0x3 << 2);
 | 
						|
  }
 | 
						|
  if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {
 | 
						|
    CpuContext->Dr2 = 0;
 | 
						|
    CpuContext->Dr7 &= ~(0x3 << 4);
 | 
						|
  }
 | 
						|
  if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {
 | 
						|
    CpuContext->Dr3 = 0;
 | 
						|
    CpuContext->Dr7 &= ~(0x3 << 6);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send acknowledge packet to HOST.
 | 
						|
 | 
						|
  @param[in] AckCommand    Type of Acknowledge packet.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SendAckPacket (
 | 
						|
  IN UINT8                AckCommand
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_COMMAND_HEADER      DebugCommonHeader;
 | 
						|
  DEBUG_PORT_HANDLE         Handle;
 | 
						|
 | 
						|
  Handle = GetDebugPortHandle();
 | 
						|
 | 
						|
  DebugCommonHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
 | 
						|
  DebugCommonHeader.Command     = AckCommand;
 | 
						|
  DebugCommonHeader.DataLength  = 0;
 | 
						|
 | 
						|
  DebugPortWriteBuffer (Handle, (UINT8 *) &DebugCommonHeader, sizeof (DEBUG_COMMAND_HEADER));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Receive acknowledge packet from HOST in specified time.
 | 
						|
 | 
						|
  @param[out] Ack           Returned acknowlege type from HOST.
 | 
						|
  @param[in]  Timeout       Time out value to wait for acknowlege from HOST.
 | 
						|
                            The unit is microsecond.
 | 
						|
  @param[out] BreakReceived If BreakReceived is not NULL,
 | 
						|
                            TRUE is retured if break-in symbol received.
 | 
						|
                            FALSE is retured if break-in symbol not received.
 | 
						|
 | 
						|
  @retval  RETRUEN_SUCCESS  Succeed to receive acknowlege packet from HOST,
 | 
						|
                            the type of acknowlege packet saved in Ack.
 | 
						|
  @retval  RETURN_TIMEOUT   Specified timeout value was up.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
ReceiveAckPacket (
 | 
						|
  OUT UINT8                     *Ack,
 | 
						|
  IN  UINTN                     Timeout,
 | 
						|
  OUT BOOLEAN                   *BreakReceived OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_COMMAND_HEADER      DebugCommonHeader;
 | 
						|
  DEBUG_PORT_HANDLE         Handle;
 | 
						|
 | 
						|
  Handle = GetDebugPortHandle();
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugCommonHeader.StartSymbol, 1, Timeout) == 0) {
 | 
						|
      return RETURN_TIMEOUT;
 | 
						|
    }
 | 
						|
    if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {
 | 
						|
      if (BreakReceived != NULL) {
 | 
						|
        SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
 | 
						|
        *BreakReceived = TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (DebugPortReadBuffer (Handle, (UINT8 *)&DebugCommonHeader.Command, sizeof (DEBUG_COMMAND_HEADER) - 1, Timeout) == 0) {
 | 
						|
    return RETURN_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
  *Ack = DebugCommonHeader.Command;
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Receive acknowledge packet OK from HOST in specified time.
 | 
						|
 | 
						|
  @param[in]  Timeout       Time out value to wait for acknowlege from HOST.
 | 
						|
                            The unit is microsecond.
 | 
						|
  @param[out] BreakReceived If BreakReceived is not NULL,
 | 
						|
                            TRUE is retured if break-in symbol received.
 | 
						|
                            FALSE is retured if break-in symbol not received.
 | 
						|
 | 
						|
  @retval  RETRUEN_SUCCESS  Succeed to receive acknowlege packet from HOST,
 | 
						|
                            the type of acknowlege packet saved in Ack.
 | 
						|
  @retval  RETURN_TIMEOUT   Specified timeout value was up.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
WaitForAckPacketOK (
 | 
						|
  IN  UINTN                     Timeout,
 | 
						|
  OUT BOOLEAN                   *BreakReceived OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  RETURN_STATUS             Status;
 | 
						|
  UINT8                     Ack;
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived);
 | 
						|
    if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||
 | 
						|
         Status == RETURN_TIMEOUT) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Receive valid packet from HOST.
 | 
						|
 | 
						|
  @param[out] InputPacket    Buffer to receive packet.
 | 
						|
  @param[out] BreakReceived  TRUE means break-in symbol received.
 | 
						|
                             FALSE means break-in symbol not received.
 | 
						|
 | 
						|
  @retval RETURN_SUCCESS   A valid package was reveived in InputPacket.
 | 
						|
  @retval RETURN_NOT_READY No valid start symbol received.
 | 
						|
  @retval RETURN_TIMEOUT   Timeout occurs.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
ReceivePacket (
 | 
						|
  OUT UINT8             *InputPacket,
 | 
						|
  OUT BOOLEAN           *BreakReceived
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_COMMAND_HEADER  *DebugHeader;
 | 
						|
  UINTN                 Received;
 | 
						|
  DEBUG_PORT_HANDLE     Handle;
 | 
						|
 | 
						|
  Handle = GetDebugPortHandle();
 | 
						|
  //
 | 
						|
  // Find the valid start symbol
 | 
						|
  //
 | 
						|
  DebugPortReadBuffer (Handle, InputPacket, 1, 0);
 | 
						|
 | 
						|
  if (*InputPacket == DEBUG_STARTING_SYMBOL_BREAK) {
 | 
						|
    *BreakReceived = TRUE;
 | 
						|
    SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
 | 
						|
  }
 | 
						|
 | 
						|
  if (*InputPacket != DEBUG_STARTING_SYMBOL_NORMAL) {
 | 
						|
    return RETURN_NOT_READY;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Read Package header
 | 
						|
  //
 | 
						|
  Received = DebugPortReadBuffer (Handle, InputPacket + 1, sizeof(DEBUG_COMMAND_HEADER_NO_START_SYMBOL), 0);
 | 
						|
  if (Received == 0) {
 | 
						|
    return RETURN_TIMEOUT;
 | 
						|
  }
 | 
						|
 | 
						|
  DebugHeader = (DEBUG_COMMAND_HEADER *) InputPacket;
 | 
						|
  //
 | 
						|
  // Read the payload if has
 | 
						|
  //
 | 
						|
  if (DebugHeader->DataLength > 0 && DebugHeader->DataLength < (DEBUG_DATA_MAXIMUM_REAL_DATA - sizeof(DEBUG_COMMAND_HEADER))) {
 | 
						|
    InputPacket = InputPacket + 1 + Received;
 | 
						|
    Received = DebugPortReadBuffer (Handle, InputPacket, DebugHeader->DataLength, 0);
 | 
						|
 | 
						|
    if (Received == 0) {
 | 
						|
      return RETURN_TIMEOUT;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return RETURN_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get current break cause.
 | 
						|
 | 
						|
  @param[in] Vector      Vector value of exception or interrupt.
 | 
						|
  @param[in] CpuContext  Pointer to save CPU context.
 | 
						|
 | 
						|
  @return The type of break cause defined by XXXX
 | 
						|
 | 
						|
**/
 | 
						|
UINT8
 | 
						|
GetBreakCause (
 | 
						|
  IN UINTN                    Vector,
 | 
						|
  IN DEBUG_CPU_CONTEXT        *CpuContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                    Cause;
 | 
						|
 | 
						|
  Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;
 | 
						|
 | 
						|
  switch (Vector) {
 | 
						|
  case DEBUG_INT1_VECTOR:
 | 
						|
  case DEBUG_INT3_VECTOR:
 | 
						|
 | 
						|
    if (Vector == DEBUG_INT1_VECTOR) {
 | 
						|
      //
 | 
						|
      // INT 1
 | 
						|
      //
 | 
						|
      if ((CpuContext->Dr6 & BIT14) != 0) {
 | 
						|
        Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;
 | 
						|
        //
 | 
						|
        // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
 | 
						|
        // (right after triggering a breakpoint to report image load/unload).
 | 
						|
        //
 | 
						|
        return Cause;
 | 
						|
 | 
						|
      } else {
 | 
						|
        Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // INT 3
 | 
						|
      //
 | 
						|
      Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (CpuContext->Dr0) {
 | 
						|
    case IMAGE_LOAD_SIGNATURE:
 | 
						|
    case IMAGE_UNLOAD_SIGNATURE:
 | 
						|
 | 
						|
      if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {
 | 
						|
 | 
						|
        Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ? 
 | 
						|
          DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case SOFT_INTERRUPT_SIGNATURE:
 | 
						|
   
 | 
						|
      if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {
 | 
						|
        Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;
 | 
						|
        CpuContext->Dr0 = 0;
 | 
						|
      } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {
 | 
						|
        Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;
 | 
						|
        CpuContext->Dr0 = 0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case DEBUG_TIMER_VECTOR:
 | 
						|
    Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    if (Vector < 20) {
 | 
						|
      Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  return Cause;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send packet with response data to HOST.
 | 
						|
 | 
						|
  @param[in] CpuContext  Pointer to saved CPU context.
 | 
						|
  @param[in] Data        Pointer to response data buffer.
 | 
						|
  @param[in] DataSize    Size of response data in byte.
 | 
						|
 | 
						|
  @retval RETURN_SUCCESS      Response data was sent successfully.
 | 
						|
  @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
SendDataResponsePacket (
 | 
						|
  IN DEBUG_CPU_CONTEXT    *CpuContext,
 | 
						|
  IN UINT8                *Data,
 | 
						|
  IN UINT16               DataSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                PacketHeader[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
 | 
						|
  BOOLEAN              LastPacket;
 | 
						|
  UINT8                Ack;
 | 
						|
  UINT8                PacketData[DEBUG_DATA_MAXIMUM_REAL_DATA];
 | 
						|
  DEBUG_PORT_HANDLE    Handle;
 | 
						|
 | 
						|
  Handle = GetDebugPortHandle();
 | 
						|
 | 
						|
  ((DEBUG_COMMAND_HEADER *)PacketHeader)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {
 | 
						|
      LastPacket = TRUE;
 | 
						|
      ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command     = DEBUG_COMMAND_OK;
 | 
						|
      ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength  = (UINT8) DataSize;
 | 
						|
      CopyMem (PacketData, Data, DataSize);
 | 
						|
 | 
						|
    } else {
 | 
						|
      LastPacket = FALSE;
 | 
						|
      ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command     = DEBUG_COMMAND_IN_PROGRESS;
 | 
						|
      ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength  = DEBUG_DATA_MAXIMUM_REAL_DATA;
 | 
						|
      CopyMem (PacketData, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);
 | 
						|
    }
 | 
						|
 | 
						|
    DebugPortWriteBuffer (Handle, PacketHeader, sizeof (DEBUG_COMMAND_HEADER));
 | 
						|
    DebugPortWriteBuffer (Handle, PacketData, ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength);
 | 
						|
 | 
						|
    ReceiveAckPacket(&Ack, 0, NULL);
 | 
						|
    switch (Ack) {
 | 
						|
    case DEBUG_COMMAND_RESEND:
 | 
						|
      //
 | 
						|
      // Send the packet again
 | 
						|
      //
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_CONTINUE:
 | 
						|
      //
 | 
						|
      // Send the rest packet
 | 
						|
      //
 | 
						|
      Data     += DEBUG_DATA_MAXIMUM_REAL_DATA;
 | 
						|
      DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_OK:
 | 
						|
      if (LastPacket) {
 | 
						|
        //
 | 
						|
        // If this is the last packet, return RETURN_SUCCESS.
 | 
						|
        //
 | 
						|
        return RETURN_SUCCESS;
 | 
						|
      } else {
 | 
						|
        return RETURN_DEVICE_ERROR;
 | 
						|
      }
 | 
						|
 | 
						|
    default:
 | 
						|
      return RETURN_DEVICE_ERROR;
 | 
						|
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send break cause packet to HOST.
 | 
						|
 | 
						|
  @param[in] Vector      Vector value of exception or interrutp.
 | 
						|
  @param[in] CpuContext  Pointer to save CPU context.
 | 
						|
 | 
						|
  @retval RETURN_SUCCESS      Response data was sent successfully.
 | 
						|
  @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
 | 
						|
 | 
						|
**/
 | 
						|
RETURN_STATUS
 | 
						|
SendBreakCausePacket (
 | 
						|
  IN UINTN                    Vector,
 | 
						|
  IN DEBUG_CPU_CONTEXT        *CpuContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG_DATA_RESPONSE_BREAK_CAUSE    DebugDataBreakCause;
 | 
						|
 | 
						|
  DebugDataBreakCause.StopAddress = CpuContext->Eip;
 | 
						|
  DebugDataBreakCause.Cause       = GetBreakCause (Vector, CpuContext);
 | 
						|
 | 
						|
  return SendDataResponsePacket (CpuContext, (UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  The main function to process communication with HOST.
 | 
						|
 | 
						|
  It received the command packet from HOST, and sent response data packet to HOST.
 | 
						|
 | 
						|
  @param[in]      Vector         Vector value of exception or interrutp.
 | 
						|
  @param[in, out] CpuContext     Pointer to saved CPU context.
 | 
						|
  @param[in]      BreakReceived  TRUE means break-in symbol received.
 | 
						|
                                 FALSE means break-in symbol not received.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
CommandCommunication (
 | 
						|
  IN     UINTN                   Vector,
 | 
						|
  IN OUT DEBUG_CPU_CONTEXT       *CpuContext,
 | 
						|
  IN     BOOLEAN                 BreakReceived
 | 
						|
  )
 | 
						|
{
 | 
						|
  RETURN_STATUS                 Status;
 | 
						|
  UINT8                         InputPacketBuffer[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
 | 
						|
  DEBUG_COMMAND_HEADER          *DebugHeader;
 | 
						|
  UINT8                         Data8;
 | 
						|
  UINT32                        Data32;
 | 
						|
  UINT64                        Data64;
 | 
						|
  UINTN                         DataN;
 | 
						|
  DEBUG_DATA_READ_MEMORY_8      *MemoryRead;
 | 
						|
  DEBUG_DATA_WRITE_MEMORY_8     *MemoryWrite;
 | 
						|
  DEBUG_DATA_READ_IO            *IoRead;
 | 
						|
  DEBUG_DATA_WRITE_IO           *IoWrite;
 | 
						|
  DEBUG_DATA_READ_REGISTER      *RegisterRead;
 | 
						|
  DEBUG_DATA_WRITE_REGISTER     *RegisterWrite;
 | 
						|
  UINT8                         *RegisterBuffer;
 | 
						|
  DEBUG_DATA_READ_MSR           *MsrRegisterRead;
 | 
						|
  DEBUG_DATA_WRITE_MSR          *MsrRegisterWrite;
 | 
						|
  DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM   RegisterGroupSegLim;
 | 
						|
  DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE  RegisterGroupSegBase;
 | 
						|
  DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;
 | 
						|
  BOOLEAN                       HaltDeferred;
 | 
						|
  DEBUG_DATA_RESPONSE_GET_EXCEPTION  Exception;
 | 
						|
  UINT32                        ProcessorIndex;
 | 
						|
  DEBUG_PORT_HANDLE             Handle;
 | 
						|
 | 
						|
  Handle = GetDebugPortHandle();
 | 
						|
 | 
						|
  ProcessorIndex  = 0;
 | 
						|
  HaltDeferred = BreakReceived;
 | 
						|
 | 
						|
  if (MultiProcessorDebugSupport) {
 | 
						|
    ProcessorIndex = GetProcessorIndex ();
 | 
						|
    SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
 | 
						|
  }
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
 | 
						|
    if (MultiProcessorDebugSupport) {
 | 
						|
      if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {
 | 
						|
        if (mDebugMpContext.RunCommandSet) {
 | 
						|
          SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
 | 
						|
          CommandGo (CpuContext);
 | 
						|
          break;
 | 
						|
        } else {
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    AcquireDebugPortControl ();
 | 
						|
 | 
						|
    Status = ReceivePacket (InputPacketBuffer, &BreakReceived);
 | 
						|
 | 
						|
    if (BreakReceived) {
 | 
						|
      HaltDeferred = TRUE;
 | 
						|
      BreakReceived = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Status != RETURN_SUCCESS) {
 | 
						|
      ReleaseDebugPortControl ();
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Data8 = 1;
 | 
						|
 | 
						|
    DebugHeader =(DEBUG_COMMAND_HEADER *) InputPacketBuffer;
 | 
						|
    switch (DebugHeader->Command) {
 | 
						|
 | 
						|
    case DEBUG_COMMAND_RESET:
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      ReleaseDebugPortControl ();
 | 
						|
 | 
						|
      ResetCold ();
 | 
						|
      //
 | 
						|
      // Wait for reset
 | 
						|
      //
 | 
						|
      CpuDeadLoop ();
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_GO:
 | 
						|
      CommandGo (CpuContext);
 | 
						|
      if (!HaltDeferred) {
 | 
						|
        //
 | 
						|
        // If no HALT command received when being in-active mode
 | 
						|
        //
 | 
						|
        if (MultiProcessorDebugSupport) {
 | 
						|
          Data32 = FindCpuNotRunning ();
 | 
						|
          if (Data32 != -1) {
 | 
						|
            //
 | 
						|
            // If there are still others processors being in break state,          
 | 
						|
            // send OK packet to HOST to finish this go command
 | 
						|
            //
 | 
						|
            SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
            CpuPause ();
 | 
						|
            //
 | 
						|
            // Set current view to the next breaking processor
 | 
						|
            //
 | 
						|
            mDebugMpContext.ViewPointIndex = Data32;
 | 
						|
            mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;
 | 
						|
            SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);
 | 
						|
            //
 | 
						|
            // Send break packet to HOST and exit to wait for command packet from HOST.
 | 
						|
            //
 | 
						|
            SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
 | 
						|
            WaitForAckPacketOK (0, &BreakReceived);
 | 
						|
            ReleaseDebugPortControl (); 
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // If no else processor break, set stop bitmask,
 | 
						|
          // and set Running flag for all processors.
 | 
						|
          //
 | 
						|
          SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
 | 
						|
          SetCpuRunningFlag (TRUE);
 | 
						|
          CpuPause ();
 | 
						|
          //
 | 
						|
          // Wait for all processors are in running state 
 | 
						|
          //
 | 
						|
          while (TRUE) {
 | 
						|
            if (IsAllCpuRunning ()) {
 | 
						|
              break;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          //
 | 
						|
          // Set BSP to be current view point.
 | 
						|
          //
 | 
						|
          SetDebugViewPoint (mDebugMpContext.BspIndex);
 | 
						|
          CpuPause ();
 | 
						|
          //
 | 
						|
          // Clear breaking processor index and running flag
 | 
						|
          //
 | 
						|
          mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
 | 
						|
          SetCpuRunningFlag (FALSE);
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Send OK packet to HOST to finish this go command
 | 
						|
        //
 | 
						|
        SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
 | 
						|
        ReleaseDebugPortControl ();
 | 
						|
 | 
						|
        return;
 | 
						|
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // If reveived HALT command, need to defer the GO command
 | 
						|
        //
 | 
						|
        SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);
 | 
						|
        HaltDeferred = FALSE;
 | 
						|
        Data8 = GetBreakCause (Vector, CpuContext);
 | 
						|
        if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
 | 
						|
          CpuContext->Dr0 = 0;
 | 
						|
          CpuContext->Dr3 = 0;
 | 
						|
        }
 | 
						|
 | 
						|
        Vector = DEBUG_TIMER_VECTOR;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_BREAK_CAUSE:
 | 
						|
 | 
						|
      if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
 | 
						|
        Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);
 | 
						|
 | 
						|
      } else {
 | 
						|
        Status = SendBreakCausePacket (Vector, CpuContext);
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_SET_HW_BREAKPOINT:
 | 
						|
      SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:
 | 
						|
      ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_SINGLE_STEPPING:
 | 
						|
      CommandStepping (CpuContext);
 | 
						|
 | 
						|
      mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
 | 
						|
 | 
						|
      ReleaseDebugPortControl ();
 | 
						|
      //
 | 
						|
      // Executing stepping command directly without sending ACK packet.
 | 
						|
      //
 | 
						|
      return;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_SET_SW_BREAKPOINT:
 | 
						|
      Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);
 | 
						|
      Data8 = *(UINT8 *) (UINTN) Data64;
 | 
						|
      *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;
 | 
						|
      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_READ_MEMORY_64:
 | 
						|
      Data8 *= 2;
 | 
						|
    case DEBUG_COMMAND_READ_MEMORY_32:
 | 
						|
      Data8 *= 2;
 | 
						|
    case DEBUG_COMMAND_READ_MEMORY_16:
 | 
						|
      Data8 *= 2;
 | 
						|
	  case DEBUG_COMMAND_READ_MEMORY_8:
 | 
						|
      MemoryRead = (DEBUG_DATA_READ_MEMORY_8 *) (DebugHeader + 1);
 | 
						|
      Status = SendDataResponsePacket (CpuContext, (UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * Data8));
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_WRITE_MEMORY_64:
 | 
						|
      Data8 *= 2;
 | 
						|
    case DEBUG_COMMAND_WRITE_MEMORY_32:
 | 
						|
      Data8 *= 2;
 | 
						|
    case DEBUG_COMMAND_WRITE_MEMORY_16:
 | 
						|
      Data8 *= 2;
 | 
						|
    case DEBUG_COMMAND_WRITE_MEMORY_8:
 | 
						|
      MemoryWrite = (DEBUG_DATA_WRITE_MEMORY_8 *) (DebugHeader + 1);
 | 
						|
      CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * Data8);
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_READ_IO:
 | 
						|
      IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);
 | 
						|
      switch (IoRead->Width) {
 | 
						|
      case 1:
 | 
						|
        Data64  = IoRead8 (IoRead->Port);
 | 
						|
        break;
 | 
						|
      case 2:
 | 
						|
        Data64  = IoRead16 (IoRead->Port);
 | 
						|
        break;
 | 
						|
      case 4:
 | 
						|
        Data64  = IoRead32 (IoRead->Port);
 | 
						|
        break;
 | 
						|
      case 8:
 | 
						|
        Data64  = IoRead64 (IoRead->Port);
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        Data64  = (UINT64) -1;
 | 
						|
      }
 | 
						|
      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, IoRead->Width);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_WRITE_IO:
 | 
						|
      IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);
 | 
						|
      switch (IoWrite->Width) {
 | 
						|
      case 1:
 | 
						|
        Data64  = IoWrite8 (IoWrite->Port, *(UINT8 *) &IoWrite->Data);
 | 
						|
        break;
 | 
						|
      case 2:
 | 
						|
        Data64  = IoWrite16 (IoWrite->Port, *(UINT16 *) &IoWrite->Data);
 | 
						|
        break;
 | 
						|
      case 4:
 | 
						|
        Data64  = IoWrite32 (IoWrite->Port, *(UINT32 *) &IoWrite->Data);
 | 
						|
        break;
 | 
						|
      case 8:
 | 
						|
        Data64  = IoWrite64 (IoWrite->Port, *(UINT64 *) &IoWrite->Data);
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        Data64  = (UINT64) -1;
 | 
						|
      }
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_READ_REGISTER:
 | 
						|
      RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);
 | 
						|
 | 
						|
      if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_OTHERS_BASE) {
 | 
						|
        Data8 = RegisterRead->Length;
 | 
						|
        RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, RegisterRead->Offset, &Data8);
 | 
						|
        Status = SendDataResponsePacket (CpuContext, RegisterBuffer, Data8);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_LIM) {
 | 
						|
        ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);
 | 
						|
        DataN = * ((UINTN *) &RegisterGroupSegLim + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_LIM));
 | 
						|
        Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
 | 
						|
      } else if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_BAS) {
 | 
						|
        ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);
 | 
						|
        DataN = * ((UINTN *) &RegisterGroupSegBase + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_BAS));
 | 
						|
        Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
 | 
						|
      } else if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_IDT_LIM) {
 | 
						|
        Data64 = ReadRegisterSelectorByIndex (CpuContext, RegisterRead->Index);
 | 
						|
        Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
 | 
						|
      } else {
 | 
						|
        switch (RegisterRead->Index) {
 | 
						|
        case SOFT_DEBUGGER_REGISTER_IDT_LIM:
 | 
						|
          DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);
 | 
						|
          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
 | 
						|
          break;
 | 
						|
        case SOFT_DEBUGGER_REGISTER_GDT_LIM:
 | 
						|
          DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);
 | 
						|
          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
 | 
						|
          break;
 | 
						|
        case SOFT_DEBUGGER_REGISTER_IDT_BAS:
 | 
						|
          DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);
 | 
						|
          DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
 | 
						|
          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
 | 
						|
          break;
 | 
						|
        case SOFT_DEBUGGER_REGISTER_GDT_BAS:
 | 
						|
          DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);
 | 
						|
          DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
 | 
						|
          SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_WRITE_REGISTER:
 | 
						|
      RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);
 | 
						|
      ArchWriteRegisterBuffer (CpuContext, RegisterWrite->Index, RegisterWrite->Offset, RegisterWrite->Length, (UINT8 *)&RegisterWrite->Value);
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_ARCH_MODE:
 | 
						|
      Data8 = DEBUG_ARCH_SYMBOL;
 | 
						|
      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_READ_MSR:
 | 
						|
      MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);
 | 
						|
      Data64 = AsmReadMsr64 (MsrRegisterRead->Index);
 | 
						|
      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_WRITE_MSR:
 | 
						|
      MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);
 | 
						|
      AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_READ_REGISTER_GROUP:
 | 
						|
      Data8 = *(UINT8 *) (DebugHeader + 1);
 | 
						|
      Status = ArchReadRegisterGroup (CpuContext, Data8);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_SET_DEBUG_FLAG:
 | 
						|
      Data32 = *(UINT32 *) (DebugHeader + 1);
 | 
						|
      SetDebugFlag (Data32);
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_GET_REVISION:
 | 
						|
      DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;
 | 
						|
      DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;
 | 
						|
      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_GET_EXCEPTION:
 | 
						|
      Exception.ExceptionNum  = (UINT8) Vector;
 | 
						|
      Exception.ExceptionData = 0;
 | 
						|
      Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_SET_VIEWPOINT:
 | 
						|
      Data32 = *(UINT32 *) (DebugHeader + 1);
 | 
						|
 | 
						|
      if (MultiProcessorDebugSupport) {
 | 
						|
        if (IsCpuStopped (Data32)) {
 | 
						|
          SetDebugViewPoint (Data32);
 | 
						|
          SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // If CPU is not halted
 | 
						|
          //
 | 
						|
          SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
 | 
						|
        }
 | 
						|
      } else if (Data32 == 0) {
 | 
						|
        SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
 | 
						|
      } else {
 | 
						|
        SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
 | 
						|
    case DEBUG_COMMAND_GET_VIEWPOINT:
 | 
						|
      Data32 = mDebugMpContext.ViewPointIndex;
 | 
						|
      SendDataResponsePacket(CpuContext, (UINT8 *) &Data32, (UINT16) sizeof (UINT32));
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Status == RETURN_UNSUPPORTED) {
 | 
						|
      SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
 | 
						|
    } else if (Status != RETURN_SUCCESS) {
 | 
						|
      SendAckPacket (DEBUG_COMMAND_ABORT);
 | 
						|
    }
 | 
						|
 | 
						|
    ReleaseDebugPortControl ();
 | 
						|
    CpuPause ();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  C function called in interrupt handler.
 | 
						|
 | 
						|
  @param[in] Vector      Vector value of exception or interrutp.
 | 
						|
  @param[in] CpuContext  Pointer to save CPU context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
InterruptProcess (
 | 
						|
  IN UINT32                          Vector,
 | 
						|
  IN DEBUG_CPU_CONTEXT               *CpuContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                     InputCharacter;
 | 
						|
  UINT8                     BreakCause;
 | 
						|
  UINTN                     SavedEip;
 | 
						|
  BOOLEAN                   BreakReceived;
 | 
						|
  UINT32                    ProcessorIndex;
 | 
						|
  UINT32                    CurrentDebugTimerInitCount;
 | 
						|
  DEBUG_PORT_HANDLE         Handle;
 | 
						|
  UINT8                     Data8;
 | 
						|
 | 
						|
  Handle = GetDebugPortHandle();
 | 
						|
 | 
						|
  ProcessorIndex = 0;
 | 
						|
  BreakReceived  = FALSE;
 | 
						|
 | 
						|
  if (MultiProcessorDebugSupport) {
 | 
						|
    ProcessorIndex = GetProcessorIndex ();
 | 
						|
    while (mDebugMpContext.RunCommandSet);
 | 
						|
  }
 | 
						|
 | 
						|
  switch (Vector) {
 | 
						|
  case DEBUG_INT1_VECTOR:
 | 
						|
  case DEBUG_INT3_VECTOR:
 | 
						|
 | 
						|
    BreakCause = GetBreakCause (Vector, CpuContext);
 | 
						|
 | 
						|
    if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {
 | 
						|
 | 
						|
      //
 | 
						|
      // Init break, if no ack received after 200ms, return
 | 
						|
      //
 | 
						|
      SendAckPacket (DEBUG_COMMAND_INIT_BREAK);
 | 
						|
      if (WaitForAckPacketOK (200 * 1000, &BreakReceived) != RETURN_SUCCESS) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      SetHostConnectedFlag ();
 | 
						|
      CommandCommunication (Vector, CpuContext, BreakReceived);
 | 
						|
 | 
						|
    } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
 | 
						|
 | 
						|
      //
 | 
						|
      // Stepping is finished, send Ack package.
 | 
						|
      //
 | 
						|
      if (MultiProcessorDebugSupport) {
 | 
						|
        mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
 | 
						|
      }
 | 
						|
      SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
      CommandCommunication (Vector, CpuContext, BreakReceived);
 | 
						|
 | 
						|
    } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_MEMORY_READY) {
 | 
						|
 | 
						|
      //
 | 
						|
      // Memory is ready
 | 
						|
      //
 | 
						|
      SendAckPacket (DEBUG_COMMAND_MEMORY_READY);
 | 
						|
      WaitForAckPacketOK (0, &BreakReceived);
 | 
						|
      CommandCommunication (Vector, CpuContext, BreakReceived);
 | 
						|
 | 
						|
    } else {
 | 
						|
 | 
						|
      if (BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
 | 
						|
        
 | 
						|
        //
 | 
						|
        // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
 | 
						|
        //
 | 
						|
        Data8 = DEBUG_AGENT_IMAGE_CONTINUE;
 | 
						|
        ArchWriteRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, 0, 1, &Data8);
 | 
						|
 | 
						|
        if (!IsHostConnected ()) {
 | 
						|
          //
 | 
						|
          // If HOST is not connected, return
 | 
						|
          //
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      AcquireDebugPortControl ();
 | 
						|
 | 
						|
      if (MultiProcessorDebugSupport) {
 | 
						|
        if(!IsAllCpuRunning ()) {
 | 
						|
          //
 | 
						|
          // If other processors have been stopped
 | 
						|
          //
 | 
						|
          SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // If no any processor was stopped, try to halt other processors
 | 
						|
          //
 | 
						|
          HaltOtherProcessors (ProcessorIndex);
 | 
						|
          SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
 | 
						|
          WaitForAckPacketOK (0, &BreakReceived);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
 | 
						|
        WaitForAckPacketOK (0, &BreakReceived);
 | 
						|
      }
 | 
						|
 | 
						|
      ReleaseDebugPortControl ();
 | 
						|
 | 
						|
      if (Vector == DEBUG_INT3_VECTOR) {
 | 
						|
        //
 | 
						|
        // go back address located "0xCC"
 | 
						|
        //
 | 
						|
        CpuContext->Eip--;
 | 
						|
        SavedEip = CpuContext->Eip;
 | 
						|
        CommandCommunication (Vector, CpuContext, BreakReceived);
 | 
						|
        if ((SavedEip == CpuContext->Eip) &&
 | 
						|
            (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {
 | 
						|
          //
 | 
						|
          // If this is not a software breakpoint set by HOST,
 | 
						|
          // restore EIP
 | 
						|
          //
 | 
						|
          CpuContext->Eip++;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        CommandCommunication (Vector, CpuContext, BreakReceived);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case DEBUG_TIMER_VECTOR:
 | 
						|
 | 
						|
    if (MultiProcessorDebugSupport) {
 | 
						|
      if (IsBsp (ProcessorIndex)) {
 | 
						|
        //
 | 
						|
        // If current processor is BSP, check Apic timer's init count if changed,
 | 
						|
        // it may be re-written when switching BSP.
 | 
						|
        // If it changed, re-initialize debug timer
 | 
						|
        //
 | 
						|
        CurrentDebugTimerInitCount = GetApicTimerInitCount ();
 | 
						|
        if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
 | 
						|
          InitializeDebugTimer ();
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
 | 
						|
        //
 | 
						|
        // If current processor is not BSP or this is one IPI sent by AP
 | 
						|
        //
 | 
						|
        if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {
 | 
						|
          CommandCommunication (Vector, CpuContext, FALSE);
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Clear EOI before exiting interrupt process routine.
 | 
						|
        //
 | 
						|
        SendApicEoi ();
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Only BSP could run here
 | 
						|
    //
 | 
						|
 | 
						|
    AcquireDebugPortControl ();
 | 
						|
    
 | 
						|
    while (DebugPortPollBuffer (Handle)) {
 | 
						|
      //
 | 
						|
      // If there is data in debug port, will check whether it is break-in symbol,
 | 
						|
      // If yes, go into communication mode with HOST.
 | 
						|
      // If no, exit interrupt process.
 | 
						|
      //
 | 
						|
      DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);
 | 
						|
      if (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK) {
 | 
						|
        SendAckPacket (DEBUG_COMMAND_OK);
 | 
						|
        if (MultiProcessorDebugSupport) {
 | 
						|
          if(FindCpuNotRunning () != -1) {
 | 
						|
            SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
 | 
						|
          } else {
 | 
						|
            HaltOtherProcessors (ProcessorIndex);
 | 
						|
          }
 | 
						|
        }
 | 
						|
        ReleaseDebugPortControl ();
 | 
						|
        CommandCommunication (Vector, CpuContext, BreakReceived);
 | 
						|
        AcquireDebugPortControl ();
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Clear EOI before exiting interrupt process routine.
 | 
						|
    //
 | 
						|
    SendApicEoi ();
 | 
						|
 | 
						|
    ReleaseDebugPortControl ();
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
 | 
						|
    if (Vector <= DEBUG_EXCEPT_SIMD) {
 | 
						|
 | 
						|
      AcquireDebugPortControl ();
 | 
						|
 | 
						|
      if (MultiProcessorDebugSupport) {
 | 
						|
        if(FindCpuNotRunning () != -1) {
 | 
						|
          SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
 | 
						|
        } else {
 | 
						|
          HaltOtherProcessors (ProcessorIndex);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
 | 
						|
      WaitForAckPacketOK (0, &BreakReceived);
 | 
						|
      ReleaseDebugPortControl ();
 | 
						|
      CommandCommunication (Vector, CpuContext, BreakReceived);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (MultiProcessorDebugSupport) {
 | 
						|
    //
 | 
						|
    // Clear flag and wait for all processors run here
 | 
						|
    //
 | 
						|
    SetIpiSentByApFlag (FALSE);
 | 
						|
    while (mDebugMpContext.RunCommandSet);
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 |