--- /dev/null
+/** @file\r
+ This file defines the debug agent GUID for HOB and configuration table.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __EFI_DEBUG_AGNET_GUID_H__\r
+#define __EFI_DEBUG_AGENT_GUID_H__\r
+\r
+///\r
+/// This guid is used as a variable GUID for the capsule variable\r
+/// if the capsule pointer is passed through reset via a variable.\r
+///\r
+/// This guid is also used as a hob GUID for the capsule data\r
+/// when the capsule pointer is passed from PEI phase to DXE phase.\r
+///\r
+#define EFI_DEBUG_AGENT_GUID \\r
+ { \\r
+ 0x865a5a9b, 0xb85d, 0x474c, { 0x84, 0x55, 0x65, 0xd1, 0xbe, 0x84, 0x4b, 0xe2 } \\r
+ }\r
+\r
+extern EFI_GUID gEfiDebugAgentGuid;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ IA32/x64 architecture specific defintions needed by debug transfer protocol.It is only\r
+ intended to be used by Debug related module implementation.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __PROCESSOR_CONTEXT_H__\r
+#define __PROCESSOR_CONTEXT_H__\r
+\r
+//\r
+// IA-32/x64 processor register index table\r
+//\r
+#define SOFT_DEBUGGER_REGISTER_DR0 0\r
+#define SOFT_DEBUGGER_REGISTER_DR1 1\r
+#define SOFT_DEBUGGER_REGISTER_DR2 2\r
+#define SOFT_DEBUGGER_REGISTER_DR3 3\r
+#define SOFT_DEBUGGER_REGISTER_DR6 4\r
+#define SOFT_DEBUGGER_REGISTER_DR7 5\r
+#define SOFT_DEBUGGER_REGISTER_EFLAGS 6\r
+#define SOFT_DEBUGGER_REGISTER_LDTR 7\r
+#define SOFT_DEBUGGER_REGISTER_TR 8\r
+#define SOFT_DEBUGGER_REGISTER_GDTR0 9 // the low 32bit of GDTR\r
+#define SOFT_DEBUGGER_REGISTER_GDTR1 10 // the high 32bit of GDTR\r
+#define SOFT_DEBUGGER_REGISTER_IDTR0 11 // the low 32bit of IDTR\r
+#define SOFT_DEBUGGER_REGISTER_IDTR1 12 // the high 32bot of IDTR\r
+#define SOFT_DEBUGGER_REGISTER_EIP 13\r
+#define SOFT_DEBUGGER_REGISTER_GS 14\r
+#define SOFT_DEBUGGER_REGISTER_FS 15\r
+#define SOFT_DEBUGGER_REGISTER_ES 16\r
+#define SOFT_DEBUGGER_REGISTER_DS 17\r
+#define SOFT_DEBUGGER_REGISTER_CS 18\r
+#define SOFT_DEBUGGER_REGISTER_SS 19\r
+#define SOFT_DEBUGGER_REGISTER_CR0 20\r
+#define SOFT_DEBUGGER_REGISTER_CR1 21\r
+#define SOFT_DEBUGGER_REGISTER_CR2 22\r
+#define SOFT_DEBUGGER_REGISTER_CR3 23\r
+#define SOFT_DEBUGGER_REGISTER_CR4 24\r
+\r
+#define SOFT_DEBUGGER_REGISTER_DI 25\r
+#define SOFT_DEBUGGER_REGISTER_SI 26\r
+#define SOFT_DEBUGGER_REGISTER_BP 27\r
+#define SOFT_DEBUGGER_REGISTER_SP 28\r
+#define SOFT_DEBUGGER_REGISTER_DX 29\r
+#define SOFT_DEBUGGER_REGISTER_CX 30\r
+#define SOFT_DEBUGGER_REGISTER_BX 31\r
+#define SOFT_DEBUGGER_REGISTER_AX 32\r
+\r
+//\r
+// This below registers are only available for x64 (not valid for Ia32 mode)\r
+//\r
+#define SOFT_DEBUGGER_REGISTER_CR8 33\r
+#define SOFT_DEBUGGER_REGISTER_R8 34\r
+#define SOFT_DEBUGGER_REGISTER_R9 35\r
+#define SOFT_DEBUGGER_REGISTER_R10 36\r
+#define SOFT_DEBUGGER_REGISTER_R11 37\r
+#define SOFT_DEBUGGER_REGISTER_R12 38\r
+#define SOFT_DEBUGGER_REGISTER_R13 39\r
+#define SOFT_DEBUGGER_REGISTER_R14 40\r
+#define SOFT_DEBUGGER_REGISTER_R15 41\r
+\r
+#define SOFT_DEBUGGER_REGISTER_MAX_COUNT_IA32 33\r
+#define SOFT_DEBUGGER_REGISTER_MAX_COUNT_X64 42\r
+\r
+//\r
+// This below registers are FP / MMX / XMM registers\r
+//\r
+#define SOFT_DEBUGGER_REGISTER_FP_BASE 50\r
+\r
+#define SOFT_DEBUGGER_REGISTER_FP_FCW (SOFT_DEBUGGER_REGISTER_FP_BASE + 0)\r
+#define SOFT_DEBUGGER_REGISTER_FP_FSW (SOFT_DEBUGGER_REGISTER_FP_BASE + 1)\r
+#define SOFT_DEBUGGER_REGISTER_FP_FTW (SOFT_DEBUGGER_REGISTER_FP_BASE + 2)\r
+#define SOFT_DEBUGGER_REGISTER_FP_OPCODE (SOFT_DEBUGGER_REGISTER_FP_BASE + 3)\r
+#define SOFT_DEBUGGER_REGISTER_FP_EIP (SOFT_DEBUGGER_REGISTER_FP_BASE + 4)\r
+#define SOFT_DEBUGGER_REGISTER_FP_CS (SOFT_DEBUGGER_REGISTER_FP_BASE + 5)\r
+#define SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET (SOFT_DEBUGGER_REGISTER_FP_BASE + 6)\r
+#define SOFT_DEBUGGER_REGISTER_FP_DS (SOFT_DEBUGGER_REGISTER_FP_BASE + 7)\r
+#define SOFT_DEBUGGER_REGISTER_FP_MXCSR (SOFT_DEBUGGER_REGISTER_FP_BASE + 8)\r
+#define SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK (SOFT_DEBUGGER_REGISTER_FP_BASE + 9)\r
+#define SOFT_DEBUGGER_REGISTER_ST0 (SOFT_DEBUGGER_REGISTER_FP_BASE + 10)\r
+#define SOFT_DEBUGGER_REGISTER_ST1 (SOFT_DEBUGGER_REGISTER_FP_BASE + 11)\r
+#define SOFT_DEBUGGER_REGISTER_ST2 (SOFT_DEBUGGER_REGISTER_FP_BASE + 12)\r
+#define SOFT_DEBUGGER_REGISTER_ST3 (SOFT_DEBUGGER_REGISTER_FP_BASE + 13)\r
+#define SOFT_DEBUGGER_REGISTER_ST4 (SOFT_DEBUGGER_REGISTER_FP_BASE + 14)\r
+#define SOFT_DEBUGGER_REGISTER_ST5 (SOFT_DEBUGGER_REGISTER_FP_BASE + 15)\r
+#define SOFT_DEBUGGER_REGISTER_ST6 (SOFT_DEBUGGER_REGISTER_FP_BASE + 16)\r
+#define SOFT_DEBUGGER_REGISTER_ST7 (SOFT_DEBUGGER_REGISTER_FP_BASE + 17)\r
+#define SOFT_DEBUGGER_REGISTER_XMM0 (SOFT_DEBUGGER_REGISTER_FP_BASE + 18)\r
+#define SOFT_DEBUGGER_REGISTER_XMM1 (SOFT_DEBUGGER_REGISTER_FP_BASE + 19)\r
+#define SOFT_DEBUGGER_REGISTER_XMM2 (SOFT_DEBUGGER_REGISTER_FP_BASE + 20)\r
+#define SOFT_DEBUGGER_REGISTER_XMM3 (SOFT_DEBUGGER_REGISTER_FP_BASE + 21)\r
+#define SOFT_DEBUGGER_REGISTER_XMM4 (SOFT_DEBUGGER_REGISTER_FP_BASE + 22)\r
+#define SOFT_DEBUGGER_REGISTER_XMM5 (SOFT_DEBUGGER_REGISTER_FP_BASE + 23)\r
+#define SOFT_DEBUGGER_REGISTER_XMM6 (SOFT_DEBUGGER_REGISTER_FP_BASE + 24)\r
+#define SOFT_DEBUGGER_REGISTER_XMM7 (SOFT_DEBUGGER_REGISTER_FP_BASE + 25)\r
+#define SOFT_DEBUGGER_REGISTER_XMM8 (SOFT_DEBUGGER_REGISTER_FP_BASE + 26)\r
+#define SOFT_DEBUGGER_REGISTER_XMM9 (SOFT_DEBUGGER_REGISTER_FP_BASE + 27)\r
+#define SOFT_DEBUGGER_REGISTER_XMM10 (SOFT_DEBUGGER_REGISTER_FP_BASE + 28)\r
+#define SOFT_DEBUGGER_REGISTER_XMM11 (SOFT_DEBUGGER_REGISTER_FP_BASE + 29)\r
+#define SOFT_DEBUGGER_REGISTER_XMM12 (SOFT_DEBUGGER_REGISTER_FP_BASE + 30)\r
+#define SOFT_DEBUGGER_REGISTER_XMM13 (SOFT_DEBUGGER_REGISTER_FP_BASE + 31)\r
+#define SOFT_DEBUGGER_REGISTER_XMM14 (SOFT_DEBUGGER_REGISTER_FP_BASE + 32)\r
+#define SOFT_DEBUGGER_REGISTER_XMM15 (SOFT_DEBUGGER_REGISTER_FP_BASE + 33)\r
+#define SOFT_DEBUGGER_REGISTER_MM0 (SOFT_DEBUGGER_REGISTER_FP_BASE + 34)\r
+#define SOFT_DEBUGGER_REGISTER_MM1 (SOFT_DEBUGGER_REGISTER_FP_BASE + 35)\r
+#define SOFT_DEBUGGER_REGISTER_MM2 (SOFT_DEBUGGER_REGISTER_FP_BASE + 36)\r
+#define SOFT_DEBUGGER_REGISTER_MM3 (SOFT_DEBUGGER_REGISTER_FP_BASE + 37)\r
+#define SOFT_DEBUGGER_REGISTER_MM4 (SOFT_DEBUGGER_REGISTER_FP_BASE + 38)\r
+#define SOFT_DEBUGGER_REGISTER_MM5 (SOFT_DEBUGGER_REGISTER_FP_BASE + 39)\r
+#define SOFT_DEBUGGER_REGISTER_MM6 (SOFT_DEBUGGER_REGISTER_FP_BASE + 40)\r
+#define SOFT_DEBUGGER_REGISTER_MM7 (SOFT_DEBUGGER_REGISTER_FP_BASE + 41)\r
+\r
+//\r
+// This below registers are for GDT, LDT, TSS\r
+//\r
+#define SOFT_DEBUGGER_REGISTER_OTHERS_BASE 100\r
+\r
+#define SOFT_DEBUGGER_REGISTER_CS_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 0)\r
+#define SOFT_DEBUGGER_REGISTER_SS_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 1)\r
+#define SOFT_DEBUGGER_REGISTER_GS_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 2)\r
+#define SOFT_DEBUGGER_REGISTER_FS_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 3)\r
+#define SOFT_DEBUGGER_REGISTER_ES_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 4)\r
+#define SOFT_DEBUGGER_REGISTER_DS_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 5)\r
+#define SOFT_DEBUGGER_REGISTER_LDT_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 6)\r
+#define SOFT_DEBUGGER_REGISTER_TSS_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 7)\r
+\r
+#define SOFT_DEBUGGER_REGISTER_CS_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 8)\r
+#define SOFT_DEBUGGER_REGISTER_SS_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 9)\r
+#define SOFT_DEBUGGER_REGISTER_GS_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 10)\r
+#define SOFT_DEBUGGER_REGISTER_FS_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 11)\r
+#define SOFT_DEBUGGER_REGISTER_ES_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 12)\r
+#define SOFT_DEBUGGER_REGISTER_DS_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 13)\r
+#define SOFT_DEBUGGER_REGISTER_LDT_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 14)\r
+#define SOFT_DEBUGGER_REGISTER_TSS_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 15)\r
+\r
+#define SOFT_DEBUGGER_REGISTER_CSAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 16)\r
+#define SOFT_DEBUGGER_REGISTER_SSAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 17)\r
+#define SOFT_DEBUGGER_REGISTER_GSAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 18)\r
+#define SOFT_DEBUGGER_REGISTER_FSAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 19)\r
+#define SOFT_DEBUGGER_REGISTER_ESAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 20)\r
+#define SOFT_DEBUGGER_REGISTER_DSAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 21)\r
+#define SOFT_DEBUGGER_REGISTER_LDTAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 22)\r
+#define SOFT_DEBUGGER_REGISTER_TSSAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 23)\r
+\r
+#define SOFT_DEBUGGER_REGISTER_IDT_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 24)\r
+#define SOFT_DEBUGGER_REGISTER_GDT_LIM (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 25)\r
+#define SOFT_DEBUGGER_REGISTER_IDT_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 26)\r
+#define SOFT_DEBUGGER_REGISTER_GDT_BAS (SOFT_DEBUGGER_REGISTER_OTHERS_BASE + 27)\r
+\r
+\r
+#define SOFT_DEBUGGER_MSR_EFER (0xC0000080)\r
+\r
+//\r
+// Definition for the Index field for DEBUG_DATA_READ_REGISTER_GROUP\r
+//\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_GPDRS32 1 //for cs,ds,es,fs,gs,ss,eflags,ebp,eip,esp,eax,ebx,ecx,edx,esi,edi,dr0,dr1,dr2,dr3,dr6,dr7\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_LIMITS32 2 //for cslim,sslim,gslim,fslim,eslim,dslim,ldtlim,tsslim\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES32 3 //for csbas,ssbas,gsbas,fsbas,esbas,dsbas,ldtbas,tssbas\r
+\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT64 4 //for cs,ds,es,fs,gs,ss\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_GP2_64 5 //for eflags,rbp,rip,rsp\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_GP64 6 //for rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_DR64 7 //for dr0,dr1,dr2,dr3,dr6,dr7\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BAS_LIM64 8 //for ldtbas,ldtlim,gdtbas,gdtlim,cslim,sslim,gslim,fslim,eslim,dslim,ldtlim,tsslim,csbas,ssbas,gsbas,fsbas,esbas,dsbas,ldtbas,tssbas\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES64 9 //for idtr,tr,csas,ssas,gsas,fsas,esas,dsas,idtas,tssas\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_CR64 10 //for cr0,cr2,cr3,cr4,cr8\r
+#define SOFT_DEBUGGER_REGISTER_GROUP_XMM64 11 //for xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15\r
+\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Public include file for Debug Agent Library instance and PE/COFF Extra\r
+ Action Library instance.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __IMAGE_DEBUG_SUPPORT_H__\r
+#define __IMAGE_DEBUG_SUPPORT_H__\r
+\r
+#define IO_PORT_BREAKPOINT_ADDRESS 0x84\r
+#define IMAGE_LOAD_SIGNATURE SIGNATURE_32('L','O','A','D')\r
+#define IMAGE_UNLOAD_SIGNATURE SIGNATURE_32('U','N','L','O')\r
+\r
+#define DEBUG_AGENT_IMAGE_WAIT 0x00\r
+#define DEBUG_AGENT_IMAGE_CONTINUE 0x01\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Debug Communication Library definitions.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __DEBUG_COMMUNICATION_LIB_H__\r
+#define __DEBUG_COMMUNICATION_LIB_H__\r
+\r
+typedef VOID * DEBUG_PORT_HANDLE;\r
+\r
+/**\r
+ Caller provided function to be invoked at the end of DebugPortInitialize().\r
+\r
+ Refer to the descrption for DebugPortInitialize() for more details.\r
+\r
+ @param[in] Context The first input argument of DebugPortInitialize().\r
+ @param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.\r
+\r
+**/\r
+typedef\r
+VOID\r
+(EFIAPI * DEBUG_PORT_CONTINUE)(\r
+ IN VOID *Context,\r
+ IN DEBUG_PORT_HANDLE DebugPortHandle\r
+ );\r
+\r
+/**\r
+ Initialize the debug port.\r
+\r
+ This function will initialize debug port to get it ready for data transmition. If\r
+ certain Debug Communication Library instance has to save some private data in the\r
+ stack, this function must work on the mode that doesn't return to the caller, then\r
+ the caller needs to wrap up all rest of logic after DebugPortInitialize() into one\r
+ function and pass it into DebugPortInitialize(). DebugPortInitialize() is\r
+ responsible to invoke the passing-in funciton at the end of DebugPortInitialize().\r
+\r
+ If the paramter Function is not NULL, Debug Communication Libary instance will\r
+ invoke it by passing in the Context to be the first parameter. Debug Communication\r
+ Library instance could create one debug port handle to be the second parameter\r
+ passing into the Function. Debug Communication Library instance also could pass\r
+ NULL to be the second parameter if it doesn't create the debug port handle.\r
+\r
+ If the parameter Function is NULL, and Context is not NULL. At this time, Context\r
+ is the debug port handle created by the previous Debug Communication Library\r
+ instance.\r
+ a) If the instance can understand and continue use the private data of the previous\r
+ instance, it could return the same handle as passed in (as Context parameter).\r
+ b) If the instance does not understand, or does not want to continue use the\r
+ private data of the previous instance, it could ignore the input Context parameter\r
+ and create the new hanlde to be returned.\r
+\r
+ If Function() is NULL and Context is NULL, Debug Communication Library could create a\r
+ new handle and return it. NULL is also a valid handle to be returned.\r
+\r
+ @param[in] Context Context needed by callback function; it was optional.\r
+ @param[in] Function Continue function called by Debug Communication library;\r
+ it was optional.\r
+\r
+ @return The debug port handle created by Debug Communication Library if Function\r
+ is not NULL.\r
+\r
+**/\r
+DEBUG_PORT_HANDLE\r
+EFIAPI\r
+DebugPortInitialize (\r
+ IN VOID *Context,\r
+ IN DEBUG_PORT_CONTINUE Function\r
+ );\r
+\r
+\r
+/**\r
+ Read data from debug device and save the datas in buffer.\r
+\r
+ Reads NumberOfBytes data bytes from a debug device into the buffer\r
+ specified by Buffer. The number of bytes actually read is returned.\r
+ If the return value is less than NumberOfBytes, then the rest operation failed.\r
+ If NumberOfBytes is zero, then return 0.\r
+\r
+ @param Handle Debug port handle.\r
+ @param Buffer Pointer to the data buffer to store the data read from the debug device.\r
+ @param NumberOfBytes Number of bytes which will be read.\r
+ @param Timeout Timeout value for reading from debug device. It unit is Microsecond.\r
+\r
+ @retval 0 Read data failed, no data is to be read.\r
+ @retval >0 Actual number of bytes read from debug device.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+DebugPortReadBuffer (\r
+ IN DEBUG_PORT_HANDLE Handle,\r
+ IN UINT8 *Buffer,\r
+ IN UINTN NumberOfBytes,\r
+ IN UINTN Timeout\r
+ );\r
+\r
+\r
+/**\r
+ Write data from buffer to debug device.\r
+\r
+ Writes NumberOfBytes data bytes from Buffer to the debug device.\r
+ The number of bytes actually written to the debug device is returned.\r
+ If the return value is less than NumberOfBytes, then the write operation failed.\r
+ If NumberOfBytes is zero, then return 0.\r
+\r
+ @param Handle Debug port handle.\r
+ @param Buffer Pointer to the data buffer to be written.\r
+ @param NumberOfBytes Number of bytes to written to the debug device.\r
+\r
+ @retval 0 NumberOfBytes is 0.\r
+ @retval >0 The number of bytes written to the debug device.\r
+ If this value is less than NumberOfBytes, then the read operation failed.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+DebugPortWriteBuffer (\r
+ IN DEBUG_PORT_HANDLE Handle,\r
+ IN UINT8 *Buffer,\r
+ IN UINTN NumberOfBytes\r
+ );\r
+\r
+/**\r
+ Polls a debug device to see if there is any data waiting to be read.\r
+\r
+ Polls a debug device to see if there is any data waiting to be read.\r
+ If there is data waiting to be read from the debug device, then TRUE is returned.\r
+ If there is no data waiting to be read from the debug device, then FALSE is returned.\r
+\r
+ @param Handle Debug port handle.\r
+\r
+ @retval TRUE Data is waiting to be read from the debug device.\r
+ @retval FALSE There is no data waiting to be read from the serial device.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+DebugPortPollBuffer (\r
+ IN DEBUG_PORT_HANDLE Handle\r
+ );\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Soft Debugger defintions. The definitions will also be used as part\r
+ of debug transfer protocol. It is only intended to be used by Debug\r
+ related module implementation.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __SOFT_DEBUGGER_DEFINITIONS_H__\r
+#define __SOFT_DEBUGGER_DEFINITIONS_H__\r
+\r
+//\r
+// Definition for processor mode (IA16, IA32, X64, ...)\r
+//\r
+#define SOFT_DEBUGGER_PROCESSOR_IA16 0\r
+#define SOFT_DEBUGGER_PROCESSOR_IA32 1\r
+#define SOFT_DEBUGGER_PROCESSOR_X64 2\r
+\r
+//\r
+// Break cause defintions\r
+//\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_UNKNOWN 0\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_HW_BREAKPOINT 1\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_STEPPING 2\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_SW_BREAKPOINT 3\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_USER_HALT 4\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_IMAGE_LOAD 5\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_IMAGE_UNLOAD 6\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_SYSTEM_RESET 7\r
+#define SOFT_DEBUGGER_BREAK_CAUSE_EXCEPTION 8\r
+\r
+#define SOFT_DEBUGGER_SETTING_SMM_ENTRY_BREAK 1\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Transfer protocol defintions used by debug agent and host. It is only\r
+ intended to be used by Debug related module implementation.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __TRANSFER_PROTOCOL_H__\r
+#define __TRANSFER_PROTOCOL_H__\r
+\r
+#include "ProcessorContext.h"\r
+#include "SoftDebuggerDefinitions.h"\r
+\r
+//\r
+// Definitions for break command.\r
+//\r
+#define DEBUG_STARTING_SYMBOL_BREAK (0x21) // '!'\r
+#define DEBUG_STARTING_SYMBOL_BREAK_STRING ("!")\r
+\r
+//\r
+// Definition for starting symbol of a normal debug packet. Choose a non-ASCII to avoid conflict with other serial output.\r
+//\r
+#define DEBUG_STARTING_SYMBOL_NORMAL (0xFE)\r
+\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// Definition for common header for normal debug packets (not including break command)\r
+//\r
+typedef struct {\r
+ UINT8 StartSymbol;\r
+ UINT8 Command;\r
+ UINT8 DataLength;\r
+} DEBUG_COMMAND_HEADER;\r
+\r
+//\r
+// Structure to facilitate debug packet header parsing or construction\r
+//\r
+typedef struct {\r
+ UINT8 Command;\r
+ UINT8 DataLength;\r
+} DEBUG_COMMAND_HEADER_NO_START_SYMBOL;\r
+\r
+\r
+//\r
+// Definition for Command field for debug packets\r
+//\r
+#define DEBUG_COMMAND_REQUEST (0 << 7)\r
+#define DEBUG_COMMAND_RESPONSE (1 << 7)\r
+\r
+\r
+\r
+#define DEBUG_COMMAND_RESET (DEBUG_COMMAND_REQUEST | 0) // 0\r
+\r
+#define DEBUG_COMMAND_GO (DEBUG_COMMAND_REQUEST | 1) // 1\r
+\r
+#define DEBUG_COMMAND_BREAK_CAUSE (DEBUG_COMMAND_REQUEST | 2) // 2\r
+\r
+#define DEBUG_COMMAND_SET_HW_BREAKPOINT (DEBUG_COMMAND_REQUEST | 3) // 3\r
+#define DEBUG_COMMAND_CLEAR_HW_BREAKPOINT (DEBUG_COMMAND_REQUEST | 4) // 4\r
+\r
+#define DEBUG_COMMAND_SINGLE_STEPPING (DEBUG_COMMAND_REQUEST | 5) // 5\r
+\r
+#define DEBUG_COMMAND_SET_SW_BREAKPOINT (DEBUG_COMMAND_REQUEST | 6) // 6\r
+#define DEBUG_COMMAND_CLEAR_SW_BREAKPOINT (DEBUG_COMMAND_REQUEST | 7) // 7\r
+\r
+#define DEBUG_COMMAND_READ_MEMORY_8 (DEBUG_COMMAND_REQUEST | 8) // 8\r
+#define DEBUG_COMMAND_READ_MEMORY_16 (DEBUG_COMMAND_REQUEST | 9) // 9\r
+#define DEBUG_COMMAND_READ_MEMORY_32 (DEBUG_COMMAND_REQUEST | 10) // 10\r
+#define DEBUG_COMMAND_READ_MEMORY_64 (DEBUG_COMMAND_REQUEST | 11) // 11\r
+\r
+#define DEBUG_COMMAND_WRITE_MEMORY_8 (DEBUG_COMMAND_REQUEST | 12) // 12\r
+#define DEBUG_COMMAND_WRITE_MEMORY_16 (DEBUG_COMMAND_REQUEST | 13) // 13\r
+#define DEBUG_COMMAND_WRITE_MEMORY_32 (DEBUG_COMMAND_REQUEST | 14) // 14\r
+#define DEBUG_COMMAND_WRITE_MEMORY_64 (DEBUG_COMMAND_REQUEST | 15) // 15\r
+\r
+#define DEBUG_COMMAND_READ_IO (DEBUG_COMMAND_REQUEST | 16) // 16\r
+#define DEBUG_COMMAND_WRITE_IO (DEBUG_COMMAND_REQUEST | 20) // 20\r
+\r
+#define DEBUG_COMMAND_READ_REGISTER (DEBUG_COMMAND_REQUEST | 24) // 24\r
+#define DEBUG_COMMAND_WRITE_REGISTER (DEBUG_COMMAND_REQUEST | 26) // 26\r
+\r
+#define DEBUG_COMMAND_STEP_OVER (DEBUG_COMMAND_REQUEST | 28) // 28\r
+#define DEBUG_COMMAND_STEP_OUT (DEBUG_COMMAND_REQUEST | 29) // 29\r
+#define DEBUG_COMMAND_STEP_BRANCH (DEBUG_COMMAND_REQUEST | 30) // 30\r
+\r
+#define DEBUG_COMMAND_ARCH_MODE (DEBUG_COMMAND_REQUEST | 34) // 34\r
+\r
+#define DEBUG_COMMAND_READ_MSR (DEBUG_COMMAND_REQUEST | 35) // 35\r
+#define DEBUG_COMMAND_WRITE_MSR (DEBUG_COMMAND_REQUEST | 36) // 36\r
+\r
+#define DEBUG_COMMAND_READ_REGISTER_GROUP (DEBUG_COMMAND_REQUEST | 37) // 37\r
+\r
+#define DEBUG_COMMAND_SET_DEBUG_FLAG (DEBUG_COMMAND_REQUEST | 38) // 38\r
+\r
+#define DEBUG_COMMAND_GET_REVISION (DEBUG_COMMAND_REQUEST | 39) // 30\r
+\r
+#define DEBUG_COMMAND_GET_EXCEPTION (DEBUG_COMMAND_REQUEST | 40) // 40\r
+\r
+#define DEBUG_COMMAND_SET_VIEWPOINT (DEBUG_COMMAND_REQUEST | 41) // 41\r
+\r
+#define DEBUG_COMMAND_GET_VIEWPOINT (DEBUG_COMMAND_REQUEST | 42) // 42\r
+\r
+//\r
+// The below are target side initiated commands.\r
+//\r
+#define DEBUG_COMMAND_INIT_BREAK (DEBUG_COMMAND_REQUEST | 63) // 63\r
+#define DEBUG_COMMAND_BREAK_POINT (DEBUG_COMMAND_REQUEST | 62) // 62\r
+#define DEBUG_COMMAND_MEMORY_READY (DEBUG_COMMAND_REQUEST | 61) // 61\r
+\r
+#define DEBUG_COMMAND_OK (DEBUG_COMMAND_RESPONSE | 0)\r
+#define DEBUG_COMMAND_RESEND (DEBUG_COMMAND_RESPONSE | 1)\r
+#define DEBUG_COMMAND_ABORT (DEBUG_COMMAND_RESPONSE | 2)\r
+\r
+//\r
+// The below 2 commands are used when transferring big data (like > ~250 bytes). The sequence is:\r
+// Host Macine Target Macine\r
+// Request =>\r
+// <= IN_PROGRESS with part of the data\r
+// CONTINUE =>\r
+// (could have multiple IN_PROGRESS and CONTINUE interactions)\r
+// <= OK with the last part of data\r
+// OK (no data as ACK) =>\r
+//\r
+#define DEBUG_COMMAND_IN_PROGRESS (DEBUG_COMMAND_RESPONSE | 3) // Used when trying to\r
+#define DEBUG_COMMAND_CONTINUE (DEBUG_COMMAND_RESPONSE | 4) // Used when trying to transfer big data (like > ~250 bytes)\r
+\r
+//\r
+// The below 2 commands are used to support deferred halt. HALT_DEFERRED will be returned when a halt request received while target is already in inter-active mode.\r
+// HALT_PROCESSED will be return as a possible return value for GO command, if target has a pending halt request.\r
+//\r
+#define DEBUG_COMMAND_HALT_DEFERRED (DEBUG_COMMAND_RESPONSE | 5)\r
+#define DEBUG_COMMAND_HALT_PROCESSED (DEBUG_COMMAND_RESPONSE | 6)\r
+\r
+#define DEBUG_COMMAND_NOT_SUPPORTED (DEBUG_COMMAND_RESPONSE | 15)\r
+\r
+//\r
+// Definition for data field for debug packets\r
+//\r
+#define DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS 20\r
+\r
+#define DEBUG_DATA_UPPER_LIMIT 0xff // This is the upper limit for the data size, by the limit of the packet header definition.\r
+\r
+#define DEBUG_DATA_MAXIMUM_REAL_DATA 0xf8\r
+\r
+#define DEBUG_DEFINITION_MAX_IO_LENGTH 4\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_BREAK_CAUSE\r
+//\r
+typedef struct {\r
+ UINT8 Cause;\r
+ UINT64 StopAddress;\r
+} DEBUG_DATA_RESPONSE_BREAK_CAUSE;\r
+\r
+//\r
+// Break type defintions for DEBUG_DATA_BREAK_CAUSE\r
+//\r
+#define DEBUG_DATA_BREAK_CAUSE_UNKNOWN 0\r
+#define DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT 1\r
+#define DEBUG_DATA_BREAK_CAUSE_STEPPING 2\r
+#define DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT 3\r
+#define DEBUG_DATA_BREAK_CAUSE_USER_HALT 4\r
+#define DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD 5\r
+#define DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD 6\r
+#define DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET 7\r
+#define DEBUG_DATA_BREAK_CAUSE_EXCEPTION 8\r
+#define DEBUG_DATA_BREAK_CAUSE_MEMORY_READY 9\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_ARCH_MODE, defined as SOFT_DEBUGGER_PROCESSOR_...\r
+//\r
+typedef struct {\r
+ UINT8 CpuMode;\r
+} DEBUG_DATA_RESPONSE_ARCH_MODE;\r
+\r
+//\r
+// Cpu architecture defintions for DEBUG_DATA_RESPONSE_ARCH_MODE\r
+//\r
+#define DEBUG_DATA_BREAK_CPU_ARCH_IA16 0\r
+#define DEBUG_DATA_BREAK_CPU_ARCH_IA32 1\r
+#define DEBUG_DATA_BREAK_CPU_ARCH_X64 2\r
+\r
+//\r
+// Command and response data for DEBUG_COMMAND_XX_YY_BREAKPOINT\r
+//\r
+typedef struct {\r
+ UINT8 Length:2; // Refer to below DEBUG_DATA_BREAKPOINT_LENGTH_XX macros\r
+ UINT8 Access:2; // Refer to below DEBUG_DATA_BREAKPOINT_ACCESS_XX macros\r
+ UINT8 Index:2; // Index of debug register\r
+ UINT8 Reserved:2;\r
+} DEBUG_DATA_BREAKPOINT_TYPE;\r
+\r
+#define DEBUG_DATA_BREAKPOINT_MEMORY_ACCESS (0x11)\r
+#define DEBUG_DATA_BREAKPOINT_IO_ACCESS (0x10)\r
+#define DEBUG_DATA_BREAKPOINT_MEMORY_WRITE (0x01)\r
+#define DEBUG_DATA_BREAKPOINT_MEMORY_EXECUTE (0x00)\r
+\r
+#define DEBUG_DATA_BREAKPOINT_LENGTH_64 (0x11)\r
+#define DEBUG_DATA_BREAKPOINT_LENGTH_32 (0x10)\r
+#define DEBUG_DATA_BREAKPOINT_LENGTH_16 (0x01)\r
+#define DEBUG_DATA_BREAKPOINT_LENGTH_8 (0x00)\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_SET_HW_BREAKPOINT\r
+//\r
+typedef struct {\r
+ DEBUG_DATA_BREAKPOINT_TYPE Type;\r
+ UINT64 Address;\r
+} DEBUG_DATA_SET_HW_BREAKPOINT;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_CLEAR_HW_BREAKPOINT\r
+//\r
+typedef struct {\r
+ UINT8 IndexMask; // 0x0f will clear all hw breakpoints\r
+} DEBUG_DATA_CLEAR_HW_BREAKPOINT;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_SET_SW_BREAKPOINT\r
+//\r
+typedef struct {\r
+ UINT64 Address;\r
+} DEBUG_DATA_SET_SW_BREAKPOINT;\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_SET_SW_BREAKPOINT\r
+//\r
+typedef struct {\r
+ UINT8 OriginalData;\r
+} DEBUG_DATA_RESPONSE_SET_SW_BREAKPOINT;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_CLEAR_SW_BREAKPOINT\r
+//\r
+typedef DEBUG_DATA_SET_SW_BREAKPOINT DEBUG_DATA_CLEAR_SW_BREAKPOINT;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_READ_MEMORY_XX\r
+//\r
+typedef struct {\r
+ UINT64 Address;\r
+ UINT16 Count;\r
+} DEBUG_DATA_READ_MEMORY_8;\r
+\r
+typedef DEBUG_DATA_READ_MEMORY_8 DEBUG_DATA_READ_MEMORY_16;\r
+\r
+typedef DEBUG_DATA_READ_MEMORY_8 DEBUG_DATA_READ_MEMORY_32;\r
+\r
+typedef DEBUG_DATA_READ_MEMORY_8 DEBUG_DATA_READ_MEMORY_64;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_WRITE_MEMORY_XX\r
+//\r
+typedef struct {\r
+ UINT64 Address;\r
+ UINT16 Count;\r
+ UINT8 Data; // The actual length for this field is decided by Width x Count\r
+} DEBUG_DATA_WRITE_MEMORY_8;\r
+\r
+typedef DEBUG_DATA_WRITE_MEMORY_8 DEBUG_DATA_WRITE_MEMORY_16;\r
+\r
+typedef DEBUG_DATA_WRITE_MEMORY_8 DEBUG_DATA_WRITE_MEMORY_32;\r
+\r
+typedef DEBUG_DATA_WRITE_MEMORY_8 DEBUG_DATA_WRITE_MEMORY_64;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_READ_IO\r
+//\r
+typedef struct {\r
+ UINT16 Port;\r
+ UINT8 Width;\r
+} DEBUG_DATA_READ_IO;\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_READ_IO\r
+//\r
+typedef struct {\r
+ UINT8 Data; // The actual length of this structure will be adjusted according to the Width field\r
+} DEBUG_DATA_RESPONSE_READ_IO;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_WRITE_IO\r
+//\r
+typedef struct {\r
+ UINT16 Port;\r
+ UINT8 Width;\r
+ UINT8 Data; // The actual length of this structure will be adjusted according to the Width field\r
+} DEBUG_DATA_WRITE_IO;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_READ_REGISTER\r
+//\r
+typedef struct {\r
+ UINT8 Index; // defined as DEBUG_DEFINITION_REGISTER_XX\r
+ UINT8 Offset:4;\r
+ UINT8 Length:4;\r
+} DEBUG_DATA_READ_REGISTER;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_WRITE_REGISTER\r
+//\r
+typedef struct {\r
+ UINT8 Index; // defined as DEBUG_DEFINITION_REGISTER_XX\r
+ UINT8 Offset:4;\r
+ UINT8 Length:4;\r
+ UINT64 Value;\r
+} DEBUG_DATA_WRITE_REGISTER;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_READ_MSR\r
+//\r
+typedef struct {\r
+ UINT32 Index;\r
+} DEBUG_DATA_READ_MSR;\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_READ_MSR\r
+//\r
+typedef struct {\r
+ UINT64 Value;\r
+} DEBUG_DATA_RESPONSE_READ_MSR;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_WRITE_MSR\r
+//\r
+typedef struct {\r
+ UINT32 Index;\r
+ UINT64 Value;\r
+} DEBUG_DATA_WRITE_MSR;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_READ_REGISTER_GROUP\r
+//\r
+typedef struct {\r
+ // For possible values, refer to the definition for DEBUG_DEFINITION_REGISTER_GROUP_XXX (in another .h file as it is architecture specific)\r
+ UINT8 Index;\r
+} DEBUG_DATA_READ_REGISTER_GROUP;\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_GET_REVISION\r
+//\r
+typedef struct {\r
+ UINT32 Revision;\r
+ UINT32 Capabilities;\r
+} DEBUG_DATA_RESPONSE_GET_REVISION;\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_GET_EXCEPTION\r
+//\r
+typedef struct {\r
+ UINT8 ExceptionNum;\r
+ UINT64 ExceptionData;\r
+} DEBUG_DATA_RESPONSE_GET_EXCEPTION;\r
+\r
+typedef struct {\r
+ UINT8 DRn; // The index of DR register which to be used as temporary breakpoint\r
+} DEBUG_DATA_STEP_OVER;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_SET_DEBUG_FLAG\r
+//\r
+typedef struct {\r
+ UINT32 DebugFlag; // The index of DR register which to be used as temporary breakpoint\r
+} DEBUG_DATA_SET_DEBUG_FLAG;\r
+\r
+//\r
+// Command data for DEBUG_COMMAND_SET_VIEWPOINT\r
+// If viewpoint is changed successfully, DEBUG_COMMAND_OK will be returned.\r
+// If viewpoint is not availabe, DEBUG_COMMAND_NOT_SUPPORTED will be returned.\r
+//\r
+typedef struct {\r
+ UINT32 ViewPoint; // The index of viewpoint will be set\r
+} DEBUG_DATA_SET_VIEWPOINT;\r
+\r
+//\r
+// Response data for DEBUG_COMMAND_GET_VIEWPOINT\r
+//\r
+typedef struct {\r
+ UINT32 ViewPoint; // The index of viewpoint will be returned\r
+} DEBUG_DATA_RESPONSE_GET_VIEWPOINT;\r
+\r
+#pragma pack()\r
+\r
+#define DEBUG_PACKET_CONSTRUCTOR_WITH_NO_DATA(DebugPacket,ShortCommandType) \\r
+ ((DEBUG_COMMAND_HEADER *)DebugPacket)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL; \\r
+ ((DEBUG_COMMAND_HEADER *)DebugPacket)->Command = DEBUG_COMMAND_##ShortCommandType; \\r
+ ((DEBUG_COMMAND_HEADER *)DebugPacket)->DataLength = 0;\r
+\r
+#define DEBUG_PACKET_CONSTRUCTOR_WITH_DATA(DebugPacket,ShortCommandType, DebugPacketDataPointer, PacketLength) \\r
+ ((DEBUG_COMMAND_HEADER *)DebugPacket)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL; \\r
+ ((DEBUG_COMMAND_HEADER *)DebugPacket)->Command = DEBUG_COMMAND_##ShortCommandType; \\r
+ ((DEBUG_COMMAND_HEADER *)DebugPacket)->DataLength = sizeof (DEBUG_DATA_##ShortCommandType); \\r
+ *DebugPacketDataPointer = (DEBUG_DATA_##ShortCommandType *)((DEBUG_COMMAND_HEADER *)DebugPacket+1); \\r
+ *PacketLength = sizeof (DEBUG_COMMAND_HEADER) + sizeof (DEBUG_DATA_##ShortCommandType);\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Commond Debug Agent library implementition. It mainly includes\r
+ the first C function called by exception/interrupt handlers,\r
+ read/write debug packet to communication with HOST based on transfer\r
+ protocol.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+#include "Ia32/DebugException.h"\r
+\r
+/**\r
+ Check if HOST is connected based on Mailbox.\r
+\r
+ @retval TRUE HOST is connected.\r
+ @retval FALSE HOST is not connected.\r
+\r
+**/\r
+BOOLEAN\r
+IsHostConnected (\r
+ VOID\r
+ )\r
+{\r
+ DEBUG_AGENT_MAILBOX *Mailbox;\r
+\r
+ Mailbox = GetMailboxPointer ();\r
+\r
+ if (Mailbox->DebugFlag.Bits.HostPresent == 1) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Set HOST connect flag in Mailbox.\r
+\r
+**/\r
+VOID\r
+SetHostConnectedFlag (\r
+ VOID\r
+ )\r
+{\r
+ DEBUG_AGENT_MAILBOX *Mailbox;\r
+\r
+ Mailbox = GetMailboxPointer ();\r
+\r
+ Mailbox->DebugFlag.Bits.HostPresent = 1;\r
+}\r
+\r
+/**\r
+ Set debug flag of Debug Agent in Mailbox.\r
+\r
+ @param DebugFlag Debug Flag defined by transfer protocol.\r
+\r
+**/\r
+VOID\r
+SetDebugFlag (\r
+ IN UINT32 DebugFlag\r
+ )\r
+{\r
+ DEBUG_AGENT_MAILBOX *Mailbox;\r
+\r
+ Mailbox = GetMailboxPointer ();\r
+\r
+ if ((DebugFlag & SOFT_DEBUGGER_SETTING_SMM_ENTRY_BREAK) != 0) {\r
+ Mailbox->DebugFlag.Bits.BreakOnNextSmi = 1;\r
+ } else {\r
+ Mailbox->DebugFlag.Bits.BreakOnNextSmi = 0;\r
+ }\r
+}\r
+\r
+/**\r
+ Exectue GO command.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+\r
+**/\r
+VOID\r
+CommandGo (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext\r
+ )\r
+{\r
+ IA32_EFLAGS32 *Eflags;\r
+\r
+ Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
+ Eflags->Bits.TF = 0;\r
+ Eflags->Bits.RF = 1;\r
+}\r
+\r
+/**\r
+ Exectue Stepping command.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+\r
+**/\r
+VOID\r
+CommandStepping (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext\r
+ )\r
+{\r
+ IA32_EFLAGS32 *Eflags;\r
+\r
+ Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;\r
+ Eflags->Bits.TF = 1;\r
+ Eflags->Bits.RF = 1;\r
+}\r
+\r
+/**\r
+ Set debug register for hardware breakpoint.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] SetHwBreakpoint Hardware breakpoint to be set.\r
+\r
+**/\r
+VOID\r
+SetDebugRegister (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint\r
+ )\r
+{\r
+ UINT8 RegisterIndex;\r
+ UINTN Dr7Value;\r
+\r
+ RegisterIndex = SetHwBreakpoint->Type.Index;\r
+\r
+ //\r
+ // Set debug address\r
+ //\r
+ * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;\r
+\r
+ Dr7Value = CpuContext->Dr7;\r
+\r
+ //\r
+ // Enable Gx, Lx\r
+ //\r
+ Dr7Value |= 0x3 << (RegisterIndex * 2);\r
+ //\r
+ // Set RWx and Lenx\r
+ //\r
+ Dr7Value &= ~(0xf0000 << (RegisterIndex * 4));\r
+ Dr7Value |= (SetHwBreakpoint->Type.Length | SetHwBreakpoint->Type.Access) << (RegisterIndex * 4);\r
+ //\r
+ // Enable GE, LE\r
+ //\r
+ Dr7Value |= 0x300;\r
+\r
+ CpuContext->Dr7 = Dr7Value;\r
+}\r
+\r
+/**\r
+ Clear debug register for hardware breakpoint.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.\r
+\r
+**/\r
+VOID\r
+ClearDebugRegister (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint\r
+ )\r
+{\r
+ if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {\r
+ CpuContext->Dr0 = 0;\r
+ CpuContext->Dr7 &= ~(0x3 << 0);\r
+ }\r
+ if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {\r
+ CpuContext->Dr1 = 0;\r
+ CpuContext->Dr7 &= ~(0x3 << 2);\r
+ }\r
+ if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {\r
+ CpuContext->Dr2 = 0;\r
+ CpuContext->Dr7 &= ~(0x3 << 4);\r
+ }\r
+ if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {\r
+ CpuContext->Dr3 = 0;\r
+ CpuContext->Dr7 &= ~(0x3 << 6);\r
+ }\r
+}\r
+\r
+/**\r
+ Send acknowledge packet to HOST.\r
+\r
+ @param[in] AckCommand Type of Acknowledge packet.\r
+\r
+**/\r
+VOID\r
+SendAckPacket (\r
+ IN UINT8 AckCommand\r
+ )\r
+{\r
+ DEBUG_COMMAND_HEADER DebugCommonHeader;\r
+ DEBUG_PORT_HANDLE Handle;\r
+\r
+ Handle = GetDebugPortHandle();\r
+\r
+ DebugCommonHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
+ DebugCommonHeader.Command = AckCommand;\r
+ DebugCommonHeader.DataLength = 0;\r
+\r
+ DebugPortWriteBuffer (Handle, (UINT8 *) &DebugCommonHeader, sizeof (DEBUG_COMMAND_HEADER));\r
+}\r
+\r
+/**\r
+ Receive acknowledge packet from HOST in specified time.\r
+\r
+ @param[out] Ack Returned acknowlege type from HOST.\r
+ @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
+ The unit is microsecond.\r
+ @param[out] BreakReceived If BreakReceived is not NULL,\r
+ TRUE is retured if break-in symbol received.\r
+ FALSE is retured if break-in symbol not received.\r
+\r
+ @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
+ the type of acknowlege packet saved in Ack.\r
+ @retval RETURN_TIMEOUT Specified timeout value was up.\r
+\r
+**/\r
+RETURN_STATUS\r
+ReceiveAckPacket (\r
+ OUT UINT8 *Ack,\r
+ IN UINTN Timeout,\r
+ OUT BOOLEAN *BreakReceived OPTIONAL\r
+ )\r
+{\r
+ DEBUG_COMMAND_HEADER DebugCommonHeader;\r
+ DEBUG_PORT_HANDLE Handle;\r
+\r
+ Handle = GetDebugPortHandle();\r
+\r
+ while (TRUE) {\r
+ if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugCommonHeader.StartSymbol, 1, Timeout) == 0) {\r
+ return RETURN_TIMEOUT;\r
+ }\r
+ if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {\r
+ if (BreakReceived != NULL) {\r
+ SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
+ *BreakReceived = TRUE;\r
+ }\r
+ }\r
+ if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {\r
+ break;\r
+ }\r
+ }\r
+ if (DebugPortReadBuffer (Handle, (UINT8 *)&DebugCommonHeader.Command, sizeof (DEBUG_COMMAND_HEADER) - 1, Timeout) == 0) {\r
+ return RETURN_TIMEOUT;\r
+ }\r
+\r
+ *Ack = DebugCommonHeader.Command;\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Receive acknowledge packet OK from HOST in specified time.\r
+\r
+ @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
+ The unit is microsecond.\r
+ @param[out] BreakReceived If BreakReceived is not NULL,\r
+ TRUE is retured if break-in symbol received.\r
+ FALSE is retured if break-in symbol not received.\r
+\r
+ @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
+ the type of acknowlege packet saved in Ack.\r
+ @retval RETURN_TIMEOUT Specified timeout value was up.\r
+\r
+**/\r
+RETURN_STATUS\r
+WaitForAckPacketOK (\r
+ IN UINTN Timeout,\r
+ OUT BOOLEAN *BreakReceived OPTIONAL\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT8 Ack;\r
+\r
+ while (TRUE) {\r
+ Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived);\r
+ if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||\r
+ Status == RETURN_TIMEOUT) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Receive valid packet from HOST.\r
+\r
+ @param[out] InputPacket Buffer to receive packet.\r
+ @param[out] BreakReceived TRUE means break-in symbol received.\r
+ FALSE means break-in symbol not received.\r
+\r
+ @retval RETURN_SUCCESS A valid package was reveived in InputPacket.\r
+ @retval RETURN_NOT_READY No valid start symbol received.\r
+ @retval RETURN_TIMEOUT Timeout occurs.\r
+\r
+**/\r
+RETURN_STATUS\r
+ReceivePacket (\r
+ OUT UINT8 *InputPacket,\r
+ OUT BOOLEAN *BreakReceived\r
+ )\r
+{\r
+ DEBUG_COMMAND_HEADER *DebugHeader;\r
+ UINTN Received;\r
+ DEBUG_PORT_HANDLE Handle;\r
+\r
+ Handle = GetDebugPortHandle();\r
+ //\r
+ // Find the valid start symbol\r
+ //\r
+ DebugPortReadBuffer (Handle, InputPacket, 1, 0);\r
+\r
+ if (*InputPacket == DEBUG_STARTING_SYMBOL_BREAK) {\r
+ *BreakReceived = TRUE;\r
+ SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);\r
+ }\r
+\r
+ if (*InputPacket != DEBUG_STARTING_SYMBOL_NORMAL) {\r
+ return RETURN_NOT_READY;\r
+ }\r
+\r
+ //\r
+ // Read Package header\r
+ //\r
+ Received = DebugPortReadBuffer (Handle, InputPacket + 1, sizeof(DEBUG_COMMAND_HEADER_NO_START_SYMBOL), 0);\r
+ if (Received == 0) {\r
+ return RETURN_TIMEOUT;\r
+ }\r
+\r
+ DebugHeader = (DEBUG_COMMAND_HEADER *) InputPacket;\r
+ //\r
+ // Read the payload if has\r
+ //\r
+ if (DebugHeader->DataLength > 0 && DebugHeader->DataLength < (DEBUG_DATA_MAXIMUM_REAL_DATA - sizeof(DEBUG_COMMAND_HEADER))) {\r
+ InputPacket = InputPacket + 1 + Received;\r
+ Received = DebugPortReadBuffer (Handle, InputPacket, DebugHeader->DataLength, 0);\r
+\r
+ if (Received == 0) {\r
+ return RETURN_TIMEOUT;\r
+ }\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get current break cause.\r
+\r
+ @param[in] Vector Vector value of exception or interrupt.\r
+ @param[in] CpuContext Pointer to save CPU context.\r
+\r
+ @return The type of break cause defined by XXXX\r
+\r
+**/\r
+UINT8\r
+GetBreakCause (\r
+ IN UINTN Vector,\r
+ IN DEBUG_CPU_CONTEXT *CpuContext\r
+ )\r
+{\r
+ UINT8 Cause;\r
+\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;\r
+\r
+ switch (Vector) {\r
+ case DEBUG_INT1_VECTOR:\r
+ case DEBUG_INT3_VECTOR:\r
+\r
+ if (Vector == DEBUG_INT1_VECTOR) {\r
+ //\r
+ // INT 1\r
+ //\r
+ if ((CpuContext->Dr6 & BIT14) != 0) {\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;\r
+\r
+ } else {\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;\r
+ }\r
+ } else {\r
+ //\r
+ // INT 3\r
+ //\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;\r
+ }\r
+\r
+ switch (CpuContext->Dr0) {\r
+ case IMAGE_LOAD_SIGNATURE:\r
+ case IMAGE_UNLOAD_SIGNATURE:\r
+\r
+ if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {\r
+\r
+ Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ? \r
+ DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);\r
+ }\r
+ break;\r
+\r
+ case SOFT_INTERRUPT_SIGNATURE:\r
+ \r
+ if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;\r
+ CpuContext->Dr0 = 0;\r
+ } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;\r
+ CpuContext->Dr0 = 0;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+\r
+ }\r
+\r
+ break;\r
+\r
+ case DEBUG_TIMER_VECTOR:\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;\r
+ break;\r
+\r
+ default:\r
+ if (Vector < 20) {\r
+ Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;\r
+ }\r
+ break;\r
+ }\r
+\r
+ return Cause;\r
+}\r
+\r
+/**\r
+ Send packet with response data to HOST.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Data Pointer to response data buffer.\r
+ @param[in] DataSize Size of response data in byte.\r
+\r
+ @retval RETURN_SUCCESS Response data was sent successfully.\r
+ @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
+\r
+**/\r
+RETURN_STATUS\r
+SendDataResponsePacket (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 *Data,\r
+ IN UINT16 DataSize\r
+ )\r
+{\r
+ UINT8 PacketHeader[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];\r
+ BOOLEAN LastPacket;\r
+ UINT8 Ack;\r
+ UINT8 PacketData[DEBUG_DATA_MAXIMUM_REAL_DATA];\r
+ DEBUG_PORT_HANDLE Handle;\r
+\r
+ Handle = GetDebugPortHandle();\r
+\r
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;\r
+\r
+ while (TRUE) {\r
+ if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {\r
+ LastPacket = TRUE;\r
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_OK;\r
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = (UINT8) DataSize;\r
+ CopyMem (PacketData, Data, DataSize);\r
+\r
+ } else {\r
+ LastPacket = FALSE;\r
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_IN_PROGRESS;\r
+ ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = DEBUG_DATA_MAXIMUM_REAL_DATA;\r
+ CopyMem (PacketData, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);\r
+ }\r
+\r
+ DebugPortWriteBuffer (Handle, PacketHeader, sizeof (DEBUG_COMMAND_HEADER));\r
+ DebugPortWriteBuffer (Handle, PacketData, ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength);\r
+\r
+ ReceiveAckPacket(&Ack, 0, NULL);\r
+ switch (Ack) {\r
+ case DEBUG_COMMAND_RESEND:\r
+ //\r
+ // Send the packet again\r
+ //\r
+ break;\r
+\r
+ case DEBUG_COMMAND_CONTINUE:\r
+ //\r
+ // Send the rest packet\r
+ //\r
+ Data += DEBUG_DATA_MAXIMUM_REAL_DATA;\r
+ DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;\r
+ break;\r
+\r
+ case DEBUG_COMMAND_OK:\r
+ if (LastPacket) {\r
+ //\r
+ // If this is the last packet, return RETURN_SUCCESS.\r
+ //\r
+ return RETURN_SUCCESS;\r
+ } else {\r
+ return RETURN_DEVICE_ERROR;\r
+ }\r
+\r
+ default:\r
+ return RETURN_DEVICE_ERROR;\r
+\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Send break cause packet to HOST.\r
+\r
+ @param[in] Vector Vector value of exception or interrutp.\r
+ @param[in] CpuContext Pointer to save CPU context.\r
+\r
+ @retval RETURN_SUCCESS Response data was sent successfully.\r
+ @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
+\r
+**/\r
+RETURN_STATUS\r
+SendBreakCausePacket (\r
+ IN UINTN Vector,\r
+ IN DEBUG_CPU_CONTEXT *CpuContext\r
+ )\r
+{\r
+ DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;\r
+\r
+ DebugDataBreakCause.StopAddress = CpuContext->Eip;\r
+ DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);\r
+\r
+ return SendDataResponsePacket (CpuContext, (UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));\r
+}\r
+\r
+\r
+/**\r
+ The main function to process communication with HOST.\r
+\r
+ It received the command packet from HOST, and sent response data packet to HOST.\r
+\r
+ @param[in] Vector Vector value of exception or interrutp.\r
+ @param[in, out] CpuContext Pointer to saved CPU context.\r
+ @param[in] BreakReceived TRUE means break-in symbol received.\r
+ FALSE means break-in symbol not received.\r
+\r
+**/\r
+VOID\r
+CommandCommunication (\r
+ IN UINTN Vector,\r
+ IN OUT DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN BOOLEAN BreakReceived\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT8 InputPacketBuffer[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];\r
+ DEBUG_COMMAND_HEADER *DebugHeader;\r
+ UINT8 Data8;\r
+ UINT32 Data32;\r
+ UINT64 Data64;\r
+ UINTN DataN;\r
+ DEBUG_DATA_READ_MEMORY_8 *MemoryRead;\r
+ DEBUG_DATA_WRITE_MEMORY_8 *MemoryWrite;\r
+ DEBUG_DATA_READ_IO *IoRead;\r
+ DEBUG_DATA_WRITE_IO *IoWrite;\r
+ DEBUG_DATA_READ_REGISTER *RegisterRead;\r
+ DEBUG_DATA_WRITE_REGISTER *RegisterWrite;\r
+ UINT8 *RegisterBuffer;\r
+ DEBUG_DATA_READ_MSR *MsrRegisterRead;\r
+ DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM RegisterGroupSegLim;\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE RegisterGroupSegBase;\r
+ DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;\r
+ BOOLEAN HaltDeferred;\r
+ DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;\r
+ UINT32 ProcessorIndex;\r
+ DEBUG_PORT_HANDLE Handle;\r
+\r
+ Handle = GetDebugPortHandle();\r
+\r
+ ProcessorIndex = 0;\r
+ HaltDeferred = BreakReceived;\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ ProcessorIndex = GetProcessorIndex ();\r
+ SetCpuStopFlagByIndex (ProcessorIndex, TRUE);\r
+ }\r
+\r
+ while (TRUE) {\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {\r
+ if (mDebugMpContext.RunCommandSet) {\r
+ SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
+ CommandGo (CpuContext);\r
+ break;\r
+ } else {\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+\r
+ AcquireDebugPortControl ();\r
+\r
+ Status = ReceivePacket (InputPacketBuffer, &BreakReceived);\r
+\r
+ if (BreakReceived) {\r
+ HaltDeferred = TRUE;\r
+ BreakReceived = FALSE;\r
+ }\r
+\r
+ if (Status != RETURN_SUCCESS) {\r
+ ReleaseDebugPortControl ();\r
+ continue;\r
+ }\r
+\r
+ Data8 = 1;\r
+\r
+ DebugHeader =(DEBUG_COMMAND_HEADER *) InputPacketBuffer;\r
+ switch (DebugHeader->Command) {\r
+\r
+ case DEBUG_COMMAND_RESET:\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ ReleaseDebugPortControl ();\r
+\r
+ ResetCold ();\r
+ //\r
+ // Wait for reset\r
+ //\r
+ CpuDeadLoop ();\r
+ break;\r
+\r
+ case DEBUG_COMMAND_GO:\r
+ CommandGo (CpuContext);\r
+ if (!HaltDeferred) {\r
+ //\r
+ // If no HALT command received when being in-active mode\r
+ //\r
+ if (MultiProcessorDebugSupport) {\r
+ Data32 = FindCpuNotRunning ();\r
+ if (Data32 != -1) {\r
+ //\r
+ // If there are still others processors being in break state, \r
+ // send OK packet to HOST to finish this go command\r
+ //\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ CpuPause ();\r
+ //\r
+ // Set current view to the next breaking processor\r
+ //\r
+ mDebugMpContext.ViewPointIndex = Data32;\r
+ mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;\r
+ SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);\r
+ //\r
+ // Send break packet to HOST and exit to wait for command packet from HOST.\r
+ //\r
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
+ WaitForAckPacketOK (0, &BreakReceived);\r
+ ReleaseDebugPortControl (); \r
+ break;\r
+ }\r
+\r
+ //\r
+ // If no else processor break, set stop bitmask,\r
+ // and set Running flag for all processors.\r
+ //\r
+ SetCpuStopFlagByIndex (ProcessorIndex, FALSE);\r
+ SetCpuRunningFlag (TRUE);\r
+ CpuPause ();\r
+ //\r
+ // Wait for all processors are in running state \r
+ //\r
+ while (TRUE) {\r
+ if (IsAllCpuRunning ()) {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Set BSP to be current view point.\r
+ //\r
+ SetDebugViewPoint (mDebugMpContext.BspIndex);\r
+ CpuPause ();\r
+ //\r
+ // Clear breaking processor index and running flag\r
+ //\r
+ mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
+ SetCpuRunningFlag (FALSE);\r
+ }\r
+\r
+ //\r
+ // Send OK packet to HOST to finish this go command\r
+ //\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+\r
+ ReleaseDebugPortControl ();\r
+\r
+ return;\r
+\r
+ } else {\r
+ //\r
+ // If reveived HALT command, need to defer the GO command\r
+ //\r
+ SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);\r
+ HaltDeferred = FALSE;\r
+ Data8 = GetBreakCause (Vector, CpuContext);\r
+ if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
+ CpuContext->Dr0 = 0;\r
+ CpuContext->Dr3 = 0;\r
+ }\r
+\r
+ Vector = DEBUG_TIMER_VECTOR;\r
+ }\r
+ break;\r
+\r
+ case DEBUG_COMMAND_BREAK_CAUSE:\r
+\r
+ if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {\r
+ Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);\r
+\r
+ } else {\r
+ Status = SendBreakCausePacket (Vector, CpuContext);\r
+ }\r
+\r
+ break;\r
+\r
+ case DEBUG_COMMAND_SET_HW_BREAKPOINT:\r
+ SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:\r
+ ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_SINGLE_STEPPING:\r
+ CommandStepping (CpuContext);\r
+\r
+ mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);\r
+\r
+ ReleaseDebugPortControl ();\r
+ //\r
+ // Executing stepping command directly without sending ACK packet.\r
+ //\r
+ return;\r
+\r
+ case DEBUG_COMMAND_SET_SW_BREAKPOINT:\r
+ Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);\r
+ Data8 = *(UINT8 *) (UINTN) Data64;\r
+ *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
+ break;\r
+\r
+ case DEBUG_COMMAND_READ_MEMORY_64:\r
+ Data8 *= 2;\r
+ case DEBUG_COMMAND_READ_MEMORY_32:\r
+ Data8 *= 2;\r
+ case DEBUG_COMMAND_READ_MEMORY_16:\r
+ Data8 *= 2;\r
+ case DEBUG_COMMAND_READ_MEMORY_8:\r
+ MemoryRead = (DEBUG_DATA_READ_MEMORY_8 *) (DebugHeader + 1);\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * Data8));\r
+ break;\r
+\r
+ case DEBUG_COMMAND_WRITE_MEMORY_64:\r
+ Data8 *= 2;\r
+ case DEBUG_COMMAND_WRITE_MEMORY_32:\r
+ Data8 *= 2;\r
+ case DEBUG_COMMAND_WRITE_MEMORY_16:\r
+ Data8 *= 2;\r
+ case DEBUG_COMMAND_WRITE_MEMORY_8:\r
+ MemoryWrite = (DEBUG_DATA_WRITE_MEMORY_8 *) (DebugHeader + 1);\r
+ CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * Data8);\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_READ_IO:\r
+ IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);\r
+ switch (IoRead->Width) {\r
+ case 1:\r
+ Data64 = IoRead8 (IoRead->Port);\r
+ break;\r
+ case 2:\r
+ Data64 = IoRead16 (IoRead->Port);\r
+ break;\r
+ case 4:\r
+ Data64 = IoRead32 (IoRead->Port);\r
+ break;\r
+ case 8:\r
+ Data64 = IoRead64 (IoRead->Port);\r
+ break;\r
+ default:\r
+ Data64 = (UINT64) -1;\r
+ }\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, IoRead->Width);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_WRITE_IO:\r
+ IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);\r
+ switch (IoWrite->Width) {\r
+ case 1:\r
+ Data64 = IoWrite8 (IoWrite->Port, *(UINT8 *) &IoWrite->Data);\r
+ break;\r
+ case 2:\r
+ Data64 = IoWrite16 (IoWrite->Port, *(UINT16 *) &IoWrite->Data);\r
+ break;\r
+ case 4:\r
+ Data64 = IoWrite32 (IoWrite->Port, *(UINT32 *) &IoWrite->Data);\r
+ break;\r
+ case 8:\r
+ Data64 = IoWrite64 (IoWrite->Port, *(UINT64 *) &IoWrite->Data);\r
+ break;\r
+ default:\r
+ Data64 = (UINT64) -1;\r
+ }\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_READ_REGISTER:\r
+ RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);\r
+\r
+ if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_OTHERS_BASE) {\r
+ Data8 = RegisterRead->Length;\r
+ RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, RegisterRead->Offset, &Data8);\r
+ Status = SendDataResponsePacket (CpuContext, RegisterBuffer, Data8);\r
+ break;\r
+ }\r
+\r
+ if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_LIM) {\r
+ ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);\r
+ DataN = * ((UINTN *) &RegisterGroupSegLim + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_LIM));\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
+ } else if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_BAS) {\r
+ ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);\r
+ DataN = * ((UINTN *) &RegisterGroupSegBase + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_BAS));\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
+ } else if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_IDT_LIM) {\r
+ Data64 = ReadRegisterSelectorByIndex (CpuContext, RegisterRead->Index);\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
+ } else {\r
+ switch (RegisterRead->Index) {\r
+ case SOFT_DEBUGGER_REGISTER_IDT_LIM:\r
+ DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_GDT_LIM:\r
+ DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_IDT_BAS:\r
+ DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);\r
+ DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_GDT_BAS:\r
+ DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);\r
+ DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case DEBUG_COMMAND_WRITE_REGISTER:\r
+ RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);\r
+ ArchWriteRegisterBuffer (CpuContext, RegisterWrite->Index, RegisterWrite->Offset, RegisterWrite->Length, (UINT8 *)&RegisterWrite->Value);\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_ARCH_MODE:\r
+ Data8 = DEBUG_ARCH_SYMBOL;\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));\r
+ break;\r
+\r
+ case DEBUG_COMMAND_READ_MSR:\r
+ MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);\r
+ Data64 = AsmReadMsr64 (MsrRegisterRead->Index);\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));\r
+ break;\r
+\r
+ case DEBUG_COMMAND_WRITE_MSR:\r
+ MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);\r
+ AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_READ_REGISTER_GROUP:\r
+ Data8 = *(UINT8 *) (DebugHeader + 1);\r
+ Status = ArchReadRegisterGroup (CpuContext, Data8);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_SET_DEBUG_FLAG:\r
+ Data32 = *(UINT32 *) (DebugHeader + 1);\r
+ SetDebugFlag (Data32);\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ break;\r
+\r
+ case DEBUG_COMMAND_GET_REVISION:\r
+ DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;\r
+ DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));\r
+ break;\r
+\r
+ case DEBUG_COMMAND_GET_EXCEPTION:\r
+ Exception.ExceptionNum = (UINT8) Vector;\r
+ Exception.ExceptionData = 0;\r
+ Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));\r
+ break;\r
+\r
+ case DEBUG_COMMAND_SET_VIEWPOINT:\r
+ Data32 = *(UINT32 *) (DebugHeader + 1);\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ if (IsCpuStopped (Data32)) {\r
+ SetDebugViewPoint (Data32);\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ } else {\r
+ //\r
+ // If CPU is not halted\r
+ //\r
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
+ }\r
+ } else if (Data32 == 0) {\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+\r
+ } else {\r
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
+ }\r
+\r
+ break;\r
+\r
+ case DEBUG_COMMAND_GET_VIEWPOINT:\r
+ Data32 = mDebugMpContext.ViewPointIndex;\r
+ SendDataResponsePacket(CpuContext, (UINT8 *) &Data32, (UINT16) sizeof (UINT32));\r
+ break;\r
+\r
+ default:\r
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
+ break;\r
+ }\r
+\r
+ if (Status == RETURN_UNSUPPORTED) {\r
+ SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);\r
+ } else if (Status != RETURN_SUCCESS) {\r
+ SendAckPacket (DEBUG_COMMAND_ABORT);\r
+ }\r
+\r
+ ReleaseDebugPortControl ();\r
+ CpuPause ();\r
+ }\r
+}\r
+\r
+/**\r
+ C function called in interrupt handler.\r
+\r
+ @param[in] Vector Vector value of exception or interrutp.\r
+ @param[in] CpuContext Pointer to save CPU context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InterruptProcess (\r
+ IN UINT32 Vector,\r
+ IN DEBUG_CPU_CONTEXT *CpuContext\r
+ )\r
+{\r
+ UINT8 InputCharacter;\r
+ UINT8 BreakCause;\r
+ UINTN SavedEip;\r
+ BOOLEAN BreakReceived;\r
+ UINT32 ProcessorIndex;\r
+ UINT32 CurrentDebugTimerInitCount;\r
+ DEBUG_PORT_HANDLE Handle;\r
+ UINT8 Data8;\r
+\r
+ Handle = GetDebugPortHandle();\r
+\r
+ ProcessorIndex = 0;\r
+ BreakReceived = FALSE;\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ ProcessorIndex = GetProcessorIndex ();\r
+ while (mDebugMpContext.RunCommandSet);\r
+ }\r
+\r
+ switch (Vector) {\r
+ case DEBUG_INT1_VECTOR:\r
+ case DEBUG_INT3_VECTOR:\r
+\r
+ BreakCause = GetBreakCause (Vector, CpuContext);\r
+\r
+ if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {\r
+\r
+ //\r
+ // Init break, if no ack received after 200ms, return\r
+ //\r
+ SendAckPacket (DEBUG_COMMAND_INIT_BREAK);\r
+ if (WaitForAckPacketOK (200 * 1000, &BreakReceived) != RETURN_SUCCESS) {\r
+ break;\r
+ }\r
+\r
+ SetHostConnectedFlag ();\r
+ CommandCommunication (Vector, CpuContext, BreakReceived);\r
+\r
+ } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {\r
+\r
+ //\r
+ // Stepping is finished, send Ack package.\r
+ //\r
+ if (MultiProcessorDebugSupport) {\r
+ mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;\r
+ }\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ CommandCommunication (Vector, CpuContext, BreakReceived);\r
+\r
+ } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_MEMORY_READY) {\r
+\r
+ //\r
+ // Memory is ready\r
+ //\r
+ SendAckPacket (DEBUG_COMMAND_MEMORY_READY);\r
+ WaitForAckPacketOK (0, &BreakReceived);\r
+ CommandCommunication (Vector, CpuContext, BreakReceived);\r
+\r
+ } else {\r
+\r
+ if (BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {\r
+ \r
+ //\r
+ // Set AL to DEBUG_AGENT_IMAGE_CONTINUE\r
+ //\r
+ Data8 = DEBUG_AGENT_IMAGE_CONTINUE;\r
+ ArchWriteRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, 0, 1, &Data8);\r
+\r
+ if (!IsHostConnected ()) {\r
+ //\r
+ // If HOST is not connected, return\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ AcquireDebugPortControl ();\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ if(!IsAllCpuRunning ()) {\r
+ //\r
+ // If other processors have been stopped\r
+ //\r
+ SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
+ } else {\r
+ //\r
+ // If no any processor was stopped, try to halt other processors\r
+ //\r
+ HaltOtherProcessors (ProcessorIndex);\r
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
+ WaitForAckPacketOK (0, &BreakReceived);\r
+ }\r
+ } else {\r
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
+ WaitForAckPacketOK (0, &BreakReceived);\r
+ }\r
+\r
+ ReleaseDebugPortControl ();\r
+\r
+ if (Vector == DEBUG_INT3_VECTOR) {\r
+ //\r
+ // go back address located "0xCC"\r
+ //\r
+ CpuContext->Eip--;\r
+ SavedEip = CpuContext->Eip;\r
+ CommandCommunication (Vector, CpuContext, BreakReceived);\r
+ if ((SavedEip == CpuContext->Eip) &&\r
+ (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {\r
+ //\r
+ // If this is not a software breakpoint set by HOST,\r
+ // restore EIP\r
+ //\r
+ CpuContext->Eip++;\r
+ }\r
+ } else {\r
+ CommandCommunication (Vector, CpuContext, BreakReceived);\r
+ }\r
+ }\r
+\r
+ break;\r
+\r
+ case DEBUG_TIMER_VECTOR:\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ if (IsBsp (ProcessorIndex)) {\r
+ //\r
+ // If current processor is BSP, check Apic timer's init count if changed,\r
+ // it may be re-written when switching BSP.\r
+ // If it changed, re-initialize debug timer\r
+ //\r
+ CurrentDebugTimerInitCount = GetApicTimerInitCount ();\r
+ if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {\r
+ InitializeDebugTimer ();\r
+ }\r
+ }\r
+\r
+ if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {\r
+ //\r
+ // If current processor is not BSP or this is one IPI sent by AP\r
+ //\r
+ if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {\r
+ CommandCommunication (Vector, CpuContext, FALSE);\r
+ }\r
+\r
+ //\r
+ // Clear EOI before exiting interrupt process routine.\r
+ //\r
+ SendApicEoi ();\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Only BSP could run here\r
+ //\r
+\r
+ AcquireDebugPortControl ();\r
+ \r
+ while (DebugPortPollBuffer (Handle)) {\r
+ //\r
+ // If there is data in debug port, will check whether it is break-in symbol,\r
+ // If yes, go into communication mode with HOST.\r
+ // If no, exit interrupt process.\r
+ //\r
+ DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);\r
+ if (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK) {\r
+ SendAckPacket (DEBUG_COMMAND_OK);\r
+ if (MultiProcessorDebugSupport) {\r
+ if(FindCpuNotRunning () != -1) {\r
+ SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
+ } else {\r
+ HaltOtherProcessors (ProcessorIndex);\r
+ }\r
+ }\r
+ ReleaseDebugPortControl ();\r
+ CommandCommunication (Vector, CpuContext, BreakReceived);\r
+ AcquireDebugPortControl ();\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Clear EOI before exiting interrupt process routine.\r
+ //\r
+ SendApicEoi ();\r
+\r
+ ReleaseDebugPortControl ();\r
+\r
+ break;\r
+\r
+ default:\r
+\r
+ if (Vector <= DEBUG_EXCEPT_SIMD) {\r
+\r
+ AcquireDebugPortControl ();\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ if(FindCpuNotRunning () != -1) {\r
+ SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);\r
+ } else {\r
+ HaltOtherProcessors (ProcessorIndex);\r
+ }\r
+ }\r
+ SendAckPacket (DEBUG_COMMAND_BREAK_POINT);\r
+ WaitForAckPacketOK (0, &BreakReceived);\r
+ ReleaseDebugPortControl ();\r
+ CommandCommunication (Vector, CpuContext, BreakReceived);\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ //\r
+ // Clear flag and wait for all processors run here\r
+ //\r
+ SetIpiSentByApFlag (FALSE);\r
+ while (mDebugMpContext.RunCommandSet);\r
+ }\r
+\r
+ return;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Command header of for Debug Agent library instance.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DEBUG_AGENT_H_\r
+#define _DEBUG_AGENT_H_\r
+\r
+#include <Register/LocalApic.h>\r
+\r
+#include <Guid/DebugAgentGuid.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/ResetSystemLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/DebugCommunicationLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/SynchronizationLib.h>\r
+#include <Library/LocalApicLib.h>\r
+\r
+#include <TransferProtocol.h>\r
+#include <ImageDebugSupport.h>\r
+\r
+#include "DebugMp.h"\r
+#include "DebugTimer.h"\r
+#include "ArchDebugSupport.h"\r
+\r
+#define DEBUG_AGENT_REVISION ((0 << 16) | 01)\r
+#define DEBUG_AGENT_CAPABILITIES 0\r
+\r
+#define DEBUG_INT1_VECTOR 1\r
+#define DEBUG_INT3_VECTOR 3\r
+#define DEBUG_TIMER_VECTOR 32\r
+#define DEBUG_MAILBOX_VECTOR 33\r
+\r
+#define SOFT_INTERRUPT_SIGNATURE SIGNATURE_32('S','O','F','T')\r
+#define SYSTEM_RESET_SIGNATURE SIGNATURE_32('S','Y','S','R')\r
+#define MEMORY_READY_SIGNATURE SIGNATURE_32('M','E','M','R')\r
+\r
+extern UINTN Exception0Handle;\r
+extern UINTN TimerInterruptHandle;\r
+extern UINT16 ExceptionStubHeaderSize;\r
+\r
+typedef union {\r
+ struct {\r
+ UINT32 HostPresent : 1;\r
+ UINT32 BreakOnNextSmi : 1;\r
+ UINT32 Reserved : 30;\r
+ } Bits;\r
+ UINT32 Uint32;\r
+} DEBUG_AGENT_FLAG;\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+ DEBUG_AGENT_FLAG DebugFlag;\r
+ UINT64 DebugPortHandle;\r
+} DEBUG_AGENT_MAILBOX;\r
+#pragma pack()\r
+\r
+typedef union {\r
+ struct {\r
+ UINT32 LimitLow : 16;\r
+ UINT32 BaseLow : 16;\r
+ UINT32 BaseMid : 8;\r
+ UINT32 Type : 4;\r
+ UINT32 System : 1;\r
+ UINT32 Dpl : 2;\r
+ UINT32 Present : 1;\r
+ UINT32 LimitHigh : 4;\r
+ UINT32 Software : 1;\r
+ UINT32 Reserved : 1;\r
+ UINT32 DefaultSize : 1;\r
+ UINT32 Granularity : 1;\r
+ UINT32 BaseHigh : 8;\r
+ } Bits;\r
+ UINT64 Uint64;\r
+} IA32_GDT;\r
+\r
+/**\r
+ Caller provided function to be invoked at the end of DebugPortInitialize().\r
+\r
+ Refer to the descrption for DebugPortInitialize() for more details.\r
+\r
+ @param[in] Context The first input argument of DebugPortInitialize().\r
+ @param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeDebugAgentPhase2 (\r
+ IN VOID *Context,\r
+ IN DEBUG_PORT_HANDLE DebugPortHandle\r
+ );\r
+\r
+/**\r
+ Initialize IDT entries to support source level debug.\r
+\r
+**/\r
+VOID\r
+InitializeDebugIdt (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Write specified register into save CPU context.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Index Register index value.\r
+ @param[in] Offset Offset in register address range\r
+ @param[in] Width Data width to read.\r
+ @param[in] RegisterBuffer Pointer to input buffer with data.\r
+\r
+**/\r
+VOID\r
+ArchWriteRegisterBuffer (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 Index,\r
+ IN UINT8 Offset,\r
+ IN UINT8 Width,\r
+ IN UINT8 *RegisterBuffer\r
+ );\r
+\r
+/**\r
+ Read register value from saved CPU context.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Index Register index value.\r
+ @param[in] Offset Offset in register address range\r
+ @param[in] Width Data width to read.\r
+\r
+ @return The address of register value.\r
+\r
+**/\r
+UINT8 *\r
+ArchReadRegisterBuffer (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 Index,\r
+ IN UINT8 Offset,\r
+ IN UINT8 *Width\r
+ );\r
+\r
+/**\r
+ Send packet with response data to HOST.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Data Pointer to response data buffer.\r
+ @param[in] DataSize Size of response data in byte.\r
+\r
+ @retval RETURN_SUCCESS Response data was sent successfully.\r
+ @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.\r
+\r
+**/\r
+RETURN_STATUS\r
+SendDataResponsePacket (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 *Data,\r
+ IN UINT16 DataSize\r
+ );\r
+\r
+/**\r
+ Read segment selector by register index.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterIndex Register Index.\r
+\r
+ @return Value of segment selector.\r
+\r
+**/\r
+UINT64\r
+ReadRegisterSelectorByIndex (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 RegisterIndex\r
+ );\r
+\r
+/**\r
+ Read group register of common registers.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroup Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroup (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup\r
+ );\r
+\r
+/**\r
+ Read group register of Segment Base.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroupSegBase Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroupSegBase (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase\r
+ );\r
+\r
+/**\r
+ Read gourp register of Segment Limit.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroupSegLim Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroupSegLim (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim\r
+ );\r
+\r
+/**\r
+ Read group register by group index.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] GroupIndex Group Index.\r
+\r
+ @retval RETURN_SUCCESS Read successfully.\r
+ @retval RETURN_NOT_SUPPORTED Group index cannot be supported.\r
+\r
+**/\r
+RETURN_STATUS\r
+ArchReadRegisterGroup (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 GroupIndex\r
+ );\r
+\r
+/**\r
+ Send acknowledge packet to HOST.\r
+\r
+ @param AckCommand Type of Acknowledge packet.\r
+\r
+**/\r
+VOID\r
+SendAckPacket (\r
+ IN UINT8 AckCommand\r
+ );\r
+\r
+/**\r
+ Receive acknowledge packet OK from HOST in specified time.\r
+\r
+ @param[in] Timeout Time out value to wait for acknowlege from HOST.\r
+ The unit is microsecond.\r
+ @param[out] BreakReceived If BreakReceived is not NULL,\r
+ TRUE is retured if break-in symbol received.\r
+ FALSE is retured if break-in symbol not received.\r
+\r
+ @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,\r
+ the type of acknowlege packet saved in Ack.\r
+ @retval RETURN_TIMEOUT Specified timeout value was up.\r
+\r
+**/\r
+RETURN_STATUS\r
+WaitForAckPacketOK (\r
+ IN UINTN Timeout,\r
+ OUT BOOLEAN *BreakReceived OPTIONAL\r
+ );\r
+\r
+/**\r
+ Check if HOST is connected based on Mailbox.\r
+\r
+ @retval TRUE HOST is connected.\r
+ @retval FALSE HOST is not connected.\r
+\r
+**/\r
+BOOLEAN\r
+IsHostConnected (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get Debug Agent Mailbox pointer.\r
+\r
+ @return Mailbox pointer.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+GetMailboxPointer (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get debug port handle.\r
+\r
+ @return Debug port handle.\r
+\r
+**/\r
+DEBUG_PORT_HANDLE\r
+GetDebugPortHandle (\r
+ VOID\r
+ );\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Multi-Processor support functions implementation.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+\r
+DEBUG_MP_CONTEXT volatile mDebugMpContext = {0,0,0,0,0,0,0,0,FALSE,FALSE};\r
+\r
+DEBUG_CPU_DATA volatile mDebugCpuData = {0};\r
+\r
+/**\r
+ Acquire access control on debug port.\r
+\r
+ It will block in the function if cannot get the access control.\r
+\r
+**/\r
+VOID\r
+AcquireDebugPortControl (\r
+ VOID\r
+ )\r
+{\r
+ if (!MultiProcessorDebugSupport) {\r
+ return;\r
+ }\r
+\r
+ while (TRUE) {\r
+ if (AcquireSpinLockOrFail (&mDebugMpContext.DebugPortSpinLock)) {\r
+ break;\r
+ }\r
+ CpuPause ();\r
+ continue;\r
+ }\r
+}\r
+\r
+/**\r
+ Release access control on debug port.\r
+\r
+**/\r
+VOID\r
+ReleaseDebugPortControl (\r
+ VOID\r
+ )\r
+{\r
+ if (!MultiProcessorDebugSupport) {\r
+ return;\r
+ }\r
+\r
+ ReleaseSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+}\r
+\r
+/**\r
+ Acquire access control on MP context.\r
+\r
+ It will block in the function if cannot get the access control.\r
+\r
+**/\r
+VOID\r
+AcquireMpContextControl (\r
+ VOID\r
+ )\r
+{\r
+ while (TRUE) {\r
+ if (AcquireSpinLockOrFail (&mDebugMpContext.MpContextSpinLock)) {\r
+ break;\r
+ }\r
+ CpuPause ();\r
+ continue;\r
+ }\r
+}\r
+\r
+/**\r
+ Release access control on MP context.\r
+\r
+**/\r
+VOID\r
+ReleaseMpContextControl (\r
+ VOID\r
+ )\r
+{\r
+ ReleaseSpinLock (&mDebugMpContext.MpContextSpinLock);\r
+}\r
+\r
+/**\r
+ Break the other processor by send IPI.\r
+\r
+ @param[in] CurrentProcessorIndex Current processor index value.\r
+\r
+**/\r
+VOID\r
+HaltOtherProcessors (\r
+ IN UINT32 CurrentProcessorIndex\r
+ )\r
+{\r
+\r
+ if (!IsBsp (CurrentProcessorIndex)) {\r
+ SetIpiSentByApFlag (TRUE);;\r
+ }\r
+\r
+ mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex;\r
+\r
+ //\r
+ // Send fixed IPI to other processors.\r
+ //\r
+ SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR);\r
+ \r
+}\r
+\r
+/**\r
+ Get the current processor's index.\r
+\r
+ @return Processor index value.\r
+\r
+**/\r
+UINT32\r
+GetProcessorIndex (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 Index;\r
+ UINT16 LocalApicID;\r
+\r
+ LocalApicID = (UINT16) GetApicId ();\r
+\r
+ AcquireMpContextControl ();\r
+\r
+ for (Index = 0; Index < mDebugCpuData.CpuCount; Index ++) {\r
+ if (mDebugCpuData.ApicID[Index] == LocalApicID) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Index == mDebugCpuData.CpuCount) {\r
+ mDebugCpuData.ApicID[Index] = LocalApicID;\r
+ mDebugCpuData.CpuCount ++ ;\r
+ }\r
+\r
+ ReleaseMpContextControl ();\r
+\r
+ return Index;\r
+}\r
+\r
+/**\r
+ Check if the specified processor is BSP or not.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+\r
+ @retval TRUE It is BSP.\r
+ @retval FALSE It isn't BSP.\r
+\r
+**/\r
+BOOLEAN\r
+IsBsp (\r
+ IN UINT32 ProcessorIndex\r
+ )\r
+{\r
+ if (AsmMsrBitFieldRead64 (MSR_IA32_APIC_BASE_ADDRESS, 8, 8) == 1) {\r
+ if (mDebugMpContext.BspIndex != ProcessorIndex) {\r
+ AcquireMpContextControl ();\r
+ mDebugMpContext.BspIndex = ProcessorIndex;\r
+ ReleaseMpContextControl ();\r
+ }\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Set processor stop flag bitmask in MP context.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+ @param[in] StopFlag TRUE means set stop flag.\r
+ FALSE means clean break flag.\r
+\r
+**/\r
+VOID\r
+SetCpuStopFlagByIndex (\r
+ IN UINT32 ProcessorIndex,\r
+ IN BOOLEAN StopFlag\r
+ )\r
+{\r
+ UINT8 Value;\r
+ UINTN Index;\r
+\r
+ AcquireMpContextControl ();\r
+\r
+ Value = mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8];\r
+ Index = ProcessorIndex % 8;\r
+ if (StopFlag) {\r
+ Value = BitFieldWrite8 (Value, Index, Index, 1);\r
+ } else {\r
+ Value = BitFieldWrite8 (Value, Index, Index, 0);\r
+ }\r
+ mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] = Value;\r
+\r
+ ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+ Set processor break flag bitmask in MP context.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+ @param[in] BreakFlag TRUE means set break flag.\r
+ FALSE means clean break flag.\r
+\r
+**/\r
+VOID\r
+SetCpuBreakFlagByIndex (\r
+ IN UINT32 ProcessorIndex,\r
+ IN BOOLEAN BreakFlag\r
+ )\r
+{\r
+ UINT8 Value;\r
+ UINTN Index;\r
+\r
+ AcquireMpContextControl ();\r
+\r
+ Value = mDebugMpContext.CpuBreakMask[ProcessorIndex / 8];\r
+ Index = ProcessorIndex % 8;\r
+ if (BreakFlag) {\r
+ Value = BitFieldWrite8 (Value, Index, Index, 1);\r
+ } else {\r
+ Value = BitFieldWrite8 (Value, Index, Index, 0);\r
+ }\r
+ mDebugMpContext.CpuBreakMask[ProcessorIndex / 8] = Value;\r
+\r
+ ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+ Check if processor is stopped already.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+\r
+ @retval TRUE Processor is stopped already.\r
+ @retval TRUE Processor isn't stopped.\r
+\r
+**/\r
+BOOLEAN\r
+IsCpuStopped (\r
+ IN UINT32 ProcessorIndex\r
+ )\r
+{\r
+ UINT8 CpuMask;\r
+\r
+ CpuMask = (UINT8) (1 << (ProcessorIndex % 8));\r
+\r
+ if ((mDebugMpContext.CpuStopStatusMask[ProcessorIndex / 8] & CpuMask) != 0) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Set the run command flag.\r
+\r
+ @param[in] RunningFlag TRUE means run command flag is set.\r
+ FALSE means run command flag is cleared.\r
+\r
+**/\r
+VOID\r
+SetCpuRunningFlag (\r
+ IN BOOLEAN RunningFlag\r
+ )\r
+{\r
+ AcquireMpContextControl ();\r
+\r
+ mDebugMpContext.RunCommandSet = RunningFlag;\r
+\r
+ ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+ Set the current view point to be debugged.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+\r
+**/\r
+VOID\r
+SetDebugViewPoint (\r
+ IN UINT32 ProcessorIndex\r
+ )\r
+{\r
+ AcquireMpContextControl ();\r
+\r
+ mDebugMpContext.ViewPointIndex = ProcessorIndex;\r
+\r
+ ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+ Initialize debug timer.\r
+\r
+ @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.\r
+ FALSE means this IPI is sent by BSP.\r
+\r
+**/\r
+VOID\r
+SetIpiSentByApFlag (\r
+ IN BOOLEAN IpiSentByApFlag\r
+ )\r
+{\r
+ AcquireMpContextControl ();\r
+\r
+ mDebugMpContext.IpiSentByAp = IpiSentByApFlag;\r
+\r
+ ReleaseMpContextControl ();\r
+}\r
+\r
+/**\r
+ Check if any processor breaks.\r
+\r
+ @retval others There is at least one processor broken, the minimum\r
+ index number of Processor returned.\r
+ @retval -1 No any processor broken.\r
+\r
+**/\r
+UINT32\r
+FindCpuNotRunning (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 Index;\r
+ \r
+ for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
+ if (mDebugMpContext.CpuBreakMask[Index] != 0) {\r
+ return (UINT32) LowBitSet32 (mDebugMpContext.CpuBreakMask[Index]) + Index * 8;\r
+ }\r
+ }\r
+ return (UINT32)-1;\r
+}\r
+ \r
+/**\r
+ Check if all processors are in running status.\r
+\r
+ @retval TRUE All processors run.\r
+ @retval FALSE At least one processor does not run.\r
+\r
+**/\r
+BOOLEAN\r
+IsAllCpuRunning (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+ \r
+ for (Index = 0; Index < DEBUG_CPU_MAX_COUNT / 8; Index ++) {\r
+ if (mDebugMpContext.CpuStopStatusMask[Index] != 0) {\r
+ return FALSE;\r
+ }\r
+ }\r
+ return TRUE;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Header file for Multi-Processor support.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DEBUG_MP_H_\r
+#define _DEBUG_MP_H_\r
+\r
+#define DEBUG_CPU_MAX_COUNT 256\r
+\r
+typedef struct {\r
+ UINT32 CpuCount; ///< Processor count\r
+ UINT16 ApicID[DEBUG_CPU_MAX_COUNT]; ///< Record the local apic id for each processor\r
+} DEBUG_CPU_DATA;\r
+\r
+typedef struct {\r
+ SPIN_LOCK MpContextSpinLock; ///< Lock for writting MP context\r
+ SPIN_LOCK DebugPortSpinLock; ///< Lock for access debug port\r
+ UINT8 CpuBreakMask[DEBUG_CPU_MAX_COUNT/8]; ///< Bitmask of all breaking CPUs\r
+ UINT8 CpuStopStatusMask[DEBUG_CPU_MAX_COUNT/8]; ///< Bitmask of CPU stop status\r
+ UINT32 ViewPointIndex; ///< Current view point to be debugged\r
+ UINT32 BspIndex; ///< Processor index value of BSP\r
+ UINT32 BreakAtCpuIndex; ///< Processor index value of the current breaking CPU\r
+ UINT32 DebugTimerInitCount; ///< Record BSP's init timer count\r
+ BOOLEAN IpiSentByAp; ///< TRUR: IPI is sent by AP. TALSE: IPI is sent by BSP\r
+ BOOLEAN RunCommandSet; ///< TRUE: RUN commmand is not executed. FALSE : RUN command is executed.\r
+} DEBUG_MP_CONTEXT;\r
+\r
+extern CONST BOOLEAN MultiProcessorDebugSupport;\r
+extern DEBUG_MP_CONTEXT volatile mDebugMpContext;\r
+extern DEBUG_CPU_DATA volatile mDebugCpuData;\r
+\r
+/**\r
+ Break the other processor by send IPI.\r
+\r
+ @param[in] CurrentProcessorIndex Current processor index value.\r
+\r
+**/\r
+VOID\r
+HaltOtherProcessors (\r
+ IN UINT32 CurrentProcessorIndex\r
+ );\r
+\r
+/**\r
+ Get the current processor's index.\r
+\r
+ @return Processor index value.\r
+\r
+**/\r
+UINT32\r
+GetProcessorIndex (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Acquire access control on MP context.\r
+\r
+ It will block in the function if cannot get the access control.\r
+\r
+**/\r
+VOID\r
+AcquireMpContextControl (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Release access control on MP context.\r
+\r
+**/\r
+VOID\r
+ReleaseMpContextControl (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Acquire access control on debug port.\r
+\r
+ It will block in the function if cannot get the access control.\r
+\r
+**/\r
+VOID\r
+AcquireDebugPortControl (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Release access control on debug port.\r
+\r
+**/\r
+VOID\r
+ReleaseDebugPortControl (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Check if the specified processor is BSP or not.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+\r
+ @retval TRUE It is BSP.\r
+ @retval FALSE It isn't BSP.\r
+\r
+**/\r
+BOOLEAN\r
+IsBsp (\r
+ IN UINT32 ProcessorIndex\r
+ );\r
+\r
+/**\r
+ Set processor stop flag bitmask in MP context.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+ @param[in] StopFlag TRUE means set stop flag.\r
+ FALSE means clean break flag.\r
+\r
+**/\r
+VOID\r
+SetCpuStopFlagByIndex (\r
+ IN UINT32 ProcessorIndex,\r
+ IN BOOLEAN StopFlag\r
+ );\r
+\r
+/**\r
+ Set processor break flag bitmask in MP context.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+ @param[in] BreakFlag TRUE means set break flag.\r
+ FALSE means clean break flag.\r
+\r
+**/\r
+VOID\r
+SetCpuBreakFlagByIndex (\r
+ IN UINT32 ProcessorIndex,\r
+ IN BOOLEAN BreakFlag\r
+ );\r
+\r
+/**\r
+ Check if processor is stopped already.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+\r
+ @retval TRUE Processor is stopped already.\r
+ @retval FALSE Processor isn't stopped.\r
+\r
+**/\r
+BOOLEAN\r
+IsCpuStopped (\r
+ IN UINT32 ProcessorIndex\r
+ );\r
+\r
+/**\r
+ Set the run command flag.\r
+\r
+ @param[in] RunningFlag TRUE means run command flag is set.\r
+ FALSE means run command flag is cleared.\r
+\r
+**/\r
+VOID\r
+SetCpuRunningFlag (\r
+ IN BOOLEAN RunningFlag\r
+ );\r
+\r
+/**\r
+ Set the current view point to be debugged.\r
+\r
+ @param[in] ProcessorIndex Processor index value.\r
+\r
+**/\r
+VOID\r
+SetDebugViewPoint (\r
+ IN UINT32 ProcessorIndex\r
+ );\r
+\r
+/**\r
+ Initialize debug timer.\r
+\r
+ @param[in] IpiSentByApFlag TRUE means this IPI is sent by AP.\r
+ FALSE means this IPI is sent by BSP.\r
+\r
+**/\r
+VOID\r
+SetIpiSentByApFlag (\r
+ IN BOOLEAN IpiSentByApFlag\r
+ );\r
+\r
+/**\r
+ Check if any processor breaks.\r
+\r
+ @retval others There is at least one processor broken, the minimum\r
+ index number of Processor returned.\r
+ @retval -1 No any processor broken.\r
+\r
+**/\r
+UINT32\r
+FindCpuNotRunning (\r
+ VOID\r
+ );\r
+ \r
+/**\r
+ Check if all processors are in running status.\r
+\r
+ @retval TRUE All processors run.\r
+ @retval FALSE At least one processor does not run.\r
+\r
+**/\r
+BOOLEAN\r
+IsAllCpuRunning (\r
+ VOID\r
+ );\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Code for debug timer to support debug agent library implementation.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+\r
+/**\r
+ Initialize CPU local APIC timer.\r
+\r
+**/\r
+VOID\r
+InitializeDebugTimer (\r
+ VOID\r
+ )\r
+{\r
+ UINTN ApicTimerDivisor;\r
+ UINT32 InitialCount;\r
+\r
+ GetApicTimerState (&ApicTimerDivisor, NULL, NULL);\r
+\r
+ //\r
+ // Cpu Local Apic timer interrupt frequency, it is set to 0.1s\r
+ //\r
+ InitialCount = (UINT32)DivU64x32 (\r
+ MultU64x64 (\r
+ PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor,\r
+ 100\r
+ ),\r
+ 1000\r
+ );\r
+\r
+ InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR);\r
+\r
+ if (MultiProcessorDebugSupport) {\r
+ mDebugMpContext.DebugTimerInitCount = InitialCount;\r
+ }\r
+}\r
+\r
+/**\r
+ Enable/Disable the interrupt of debug timer and return the interrupt state\r
+ prior to the operation.\r
+\r
+ If EnableStatus is TRUE, enable the interrupt of debug timer.\r
+ If EnableStatus is FALSE, disable the interrupt of debug timer.\r
+\r
+ @param[in] EnableStatus Enable/Disable.\r
+\r
+ @retval TRUE Debug timer interrupt were enabled on entry to this call.\r
+ @retval FALSE Debug timer interrupt were disabled on entry to this call.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+SaveAndSetDebugTimerInterrupt (\r
+ IN BOOLEAN EnableStatus\r
+ )\r
+{\r
+ BOOLEAN OldInterruptState;\r
+ BOOLEAN OldDebugTimerInterruptState;\r
+\r
+ OldInterruptState = SaveAndDisableInterrupts ();\r
+ OldDebugTimerInterruptState = GetApicTimerInterruptState ();\r
+ \r
+ if (EnableStatus) {\r
+ EnableApicTimerInterrupt ();\r
+ } else {\r
+ DisableApicTimerInterrupt ();\r
+ }\r
+\r
+ SetInterruptState (OldInterruptState);\r
+ return OldDebugTimerInterruptState;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Header file for debug timer to support debug agent library implementation.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DEBUG_TIMER_H_\r
+#define _DEBUG_TIMER_H_\r
+\r
+/**\r
+ Initialize debug timer.\r
+\r
+**/\r
+VOID\r
+InitializeDebugTimer (\r
+ VOID\r
+ );\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+ Public include file for Debug Port Library.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+\r
+/**\r
+ Read the offset of FP / MMX / XMM registers by register index.\r
+\r
+ @param[in] Index Register index.\r
+ @param[out] Width Register width returned.\r
+\r
+ @return Offset in register address range.\r
+\r
+**/\r
+UINT16\r
+ArchReadFxStatOffset (\r
+ IN UINT8 Index,\r
+ OUT UINT8 *Width\r
+ )\r
+{\r
+ if (Index < SOFT_DEBUGGER_REGISTER_ST0) {\r
+ switch (Index) {\r
+ case SOFT_DEBUGGER_REGISTER_FP_FCW:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fcw);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_FSW:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Fsw);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_FTW:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ftw);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_OPCODE:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Opcode);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_EIP:\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Eip);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_CS:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Cs);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, DataOffset);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_DS:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Ds);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR:\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ return (UINT16)OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, Mxcsr_Mask);\r
+ }\r
+ }\r
+\r
+ if (Index < SOFT_DEBUGGER_REGISTER_XMM0) {\r
+ *Width = 10;\r
+ } else if (Index < SOFT_DEBUGGER_REGISTER_MM0 ) {\r
+ *Width = 16;\r
+ } else {\r
+ *Width = 8;\r
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
+ }\r
+\r
+ return (UINT16)(OFFSET_OF(DEBUG_DATA_IA32_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16);\r
+}\r
+\r
+/**\r
+ Write specified register into save CPU context.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Index Register index value.\r
+ @param[in] Offset Offset in register address range.\r
+ @param[in] Width Data width to read.\r
+ @param[in] RegisterBuffer Pointer to input buffer with data.\r
+\r
+**/\r
+VOID\r
+ArchWriteRegisterBuffer (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 Index,\r
+ IN UINT8 Offset,\r
+ IN UINT8 Width,\r
+ IN UINT8 *RegisterBuffer\r
+ )\r
+{\r
+ UINT8 *Buffer;\r
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;\r
+ } else {\r
+ //\r
+ // If it is MMX register, adjust its index position\r
+ //\r
+ if (Index >= SOFT_DEBUGGER_REGISTER_MM0) {\r
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
+ }\r
+ //\r
+ // FPU/MMX/XMM registers\r
+ //\r
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, &Width);\r
+ }\r
+\r
+ CopyMem (Buffer + Offset, RegisterBuffer, Width);\r
+}\r
+\r
+/**\r
+ Read register value from saved CPU context.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Index Register index value.\r
+ @param[in] Offset Offset in register address range\r
+ @param[in] Width Data width to read.\r
+\r
+ @return The address of register value.\r
+\r
+**/\r
+UINT8 *\r
+ArchReadRegisterBuffer (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 Index,\r
+ IN UINT8 Offset,\r
+ IN UINT8 *Width\r
+ )\r
+{\r
+ UINT8 *Buffer;\r
+\r
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_IA32_FX_SAVE_STATE) + Index * 4;\r
+ if (*Width == 0) {\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ }\r
+ } else {\r
+ //\r
+ // FPU/MMX/XMM registers\r
+ //\r
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, Width);\r
+ }\r
+\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Read group register of common registers.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroup Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroup (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup\r
+ )\r
+{\r
+ RegisterGroup->Cs = (UINT16) CpuContext->Cs;\r
+ RegisterGroup->Ds = (UINT16) CpuContext->Ds;\r
+ RegisterGroup->Es = (UINT16) CpuContext->Es;\r
+ RegisterGroup->Fs = (UINT16) CpuContext->Fs;\r
+ RegisterGroup->Gs = (UINT16) CpuContext->Gs;\r
+ RegisterGroup->Ss = (UINT16) CpuContext->Ss;\r
+ RegisterGroup->Eflags = CpuContext->Eflags;\r
+ RegisterGroup->Ebp = CpuContext->Ebp;\r
+ RegisterGroup->Eip = CpuContext->Eip;\r
+ RegisterGroup->Esp = CpuContext->Esp;\r
+ RegisterGroup->Eax = CpuContext->Eax;\r
+ RegisterGroup->Ebx = CpuContext->Ebx;\r
+ RegisterGroup->Ecx = CpuContext->Ecx;\r
+ RegisterGroup->Edx = CpuContext->Edx;\r
+ RegisterGroup->Esi = CpuContext->Esi;\r
+ RegisterGroup->Edi = CpuContext->Edi;\r
+ RegisterGroup->Dr0 = CpuContext->Dr0;\r
+ RegisterGroup->Dr1 = CpuContext->Dr1;\r
+ RegisterGroup->Dr2 = CpuContext->Dr2;\r
+ RegisterGroup->Dr3 = CpuContext->Dr3;\r
+ RegisterGroup->Dr6 = CpuContext->Dr6;\r
+ RegisterGroup->Dr7 = CpuContext->Dr7;\r
+}\r
+\r
+/**\r
+ Initialize IDT entries to support source level debug.\r
+\r
+**/\r
+VOID\r
+InitializeDebugIdt (\r
+ VOID\r
+ )\r
+{\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;\r
+ UINTN InterruptHandler;\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+ UINTN Index;\r
+ UINT16 CodeSegment;\r
+\r
+ AsmReadIdtr (&IdtDescriptor);\r
+\r
+ //\r
+ // Use current CS as the segment selector of interrupt gate in IDT\r
+ //\r
+ CodeSegment = AsmReadCs ();\r
+\r
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+ for (Index = 0; Index < 20; Index ++) {\r
+ if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {\r
+ //\r
+ // If the exception is masked to be reserved, skip it\r
+ //\r
+ continue;\r
+ }\r
+ InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;\r
+ IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;\r
+ IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
+ IdtEntry[Index].Bits.Selector = CodeSegment;\r
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+ }\r
+\r
+ InterruptHandler = (UINTN) &TimerInterruptHandle;\r
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;\r
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
+ IdtEntry[Index].Bits.Selector = CodeSegment;\r
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+}\r
--- /dev/null
+/** @file\r
+ IA32 specific defintions for debug agent library instance.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _ARCH_DEBUG_SUPPORT_H_\r
+#define _ARCH_DEBUG_SUPPORT_H_\r
+\r
+#include "ArchRegisters.h"\r
+#include "TransferProtocol.h"\r
+\r
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP;\r
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM;\r
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_IA32 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE;\r
+\r
+#define DEBUG_SW_BREAKPOINT_SYMBOL 0xcc\r
+\r
+#define DEBUG_ARCH_SYMBOL DEBUG_DATA_BREAK_CPU_ARCH_IA32\r
+\r
+typedef DEBUG_DATA_IA32_SYSTEM_CONTEXT DEBUG_CPU_CONTEXT;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ IA32 Group registers read support functions.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+\r
+/**\r
+ Read group register of Segment Base.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroupSegBase Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroupSegBase (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase\r
+ )\r
+{\r
+ IA32_DESCRIPTOR *Ia32Descriptor;\r
+ IA32_GDT *Ia32Gdt;\r
+ UINTN Index;\r
+\r
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;\r
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);\r
+\r
+ Index = CpuContext->Cs / 8;\r
+ RegisterGroupSegBase->CsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Ss / 8;\r
+ RegisterGroupSegBase->SsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Gs / 8;\r
+ RegisterGroupSegBase->GsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Fs / 8;\r
+ RegisterGroupSegBase->FsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Es / 8;\r
+ RegisterGroupSegBase->EsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Ds / 8;\r
+ RegisterGroupSegBase->DsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+\r
+ RegisterGroupSegBase->LdtBas = 0;\r
+ RegisterGroupSegBase->TssBas = 0;\r
+}\r
+\r
+/**\r
+ Read gourp register of Segment Limit.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroupSegLim Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroupSegLim (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim\r
+ )\r
+{\r
+ IA32_DESCRIPTOR *Ia32Descriptor;\r
+ IA32_GDT *Ia32Gdt;\r
+ UINTN Index;\r
+\r
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;\r
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);\r
+\r
+ Index = CpuContext->Cs / 8;\r
+ RegisterGroupSegLim->CsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->CsLim = (RegisterGroupSegLim->CsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Ss / 8;\r
+ RegisterGroupSegLim->SsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->SsLim = (RegisterGroupSegLim->SsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Gs / 8;\r
+ RegisterGroupSegLim->GsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->GsLim = (RegisterGroupSegLim->GsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Fs / 8;\r
+ RegisterGroupSegLim->FsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->FsLim = (RegisterGroupSegLim->FsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Es / 8;\r
+ RegisterGroupSegLim->EsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->EsLim = (RegisterGroupSegLim->EsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Ds / 8;\r
+ RegisterGroupSegLim->DsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->DsLim = (RegisterGroupSegLim->DsLim << 12) | 0xfff;\r
+ }\r
+\r
+ RegisterGroupSegLim->LdtLim = 0xffff;\r
+ RegisterGroupSegLim->TssLim = 0xffff;\r
+}\r
+\r
+/**\r
+ Read group register by group index.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] GroupIndex Group Index.\r
+\r
+ @retval RETURN_SUCCESS Read successfully.\r
+ @retval RETURN_NOT_SUPPORTED Group index cannot be supported.\r
+\r
+**/\r
+RETURN_STATUS\r
+ArchReadRegisterGroup (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 GroupIndex\r
+ )\r
+{\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP RegisterGroup;\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM RegisterGroupSegLim;\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE RegisterGroupSegBase;\r
+\r
+ switch (GroupIndex) {\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_GPDRS32:\r
+ ReadRegisterGroup (CpuContext, &RegisterGroup);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_LIMITS32:\r
+ ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupSegLim, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES32:\r
+ ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupSegBase, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE));\r
+ break;\r
+\r
+ default:\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Read segment selector by register index.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterIndex Register Index.\r
+\r
+ @return Value of segment selector.\r
+\r
+**/\r
+UINT64\r
+ReadRegisterSelectorByIndex (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 RegisterIndex\r
+ )\r
+{\r
+ IA32_DESCRIPTOR *Ia32Descriptor;\r
+ IA32_GDT *Ia32Gdt;\r
+ UINT16 Selector;\r
+ UINT32 Data32;\r
+\r
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;\r
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);\r
+\r
+ Selector = 0;\r
+\r
+ switch (RegisterIndex) {\r
+ case SOFT_DEBUGGER_REGISTER_CSAS:\r
+ Selector = (UINT16) CpuContext->Cs;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_SSAS:\r
+ Selector = (UINT16) CpuContext->Ss;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_GSAS:\r
+ Selector = (UINT16) CpuContext->Gs;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_FSAS:\r
+ Selector = (UINT16) CpuContext->Fs;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_ESAS:\r
+ Selector = (UINT16) CpuContext->Es;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_DSAS:\r
+ Selector = (UINT16) CpuContext->Ds;\r
+ case SOFT_DEBUGGER_REGISTER_LDTAS:\r
+ case SOFT_DEBUGGER_REGISTER_TSSAS:\r
+ return 0x00820000;\r
+ break;\r
+ }\r
+\r
+ Data32 = (UINT32) RShiftU64 (Ia32Gdt[Selector / 8].Uint64, 24);\r
+ return (Data32 & (UINT32)(~0xff)) | Selector;\r
+\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ IA32 register defintions needed by debug transfer protocol.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _ARCH_REGISTERS_H_\r
+#define _ARCH_REGISTERS_H_\r
+\r
+///\r
+/// FXSAVE_STATE\r
+/// FP / MMX / XMM registers (see fxrstor instruction definition)\r
+///\r
+typedef struct {\r
+ UINT16 Fcw;\r
+ UINT16 Fsw;\r
+ UINT16 Ftw;\r
+ UINT16 Opcode;\r
+ UINT32 Eip;\r
+ UINT16 Cs;\r
+ UINT16 Reserved1;\r
+ UINT32 DataOffset;\r
+ UINT16 Ds;\r
+ UINT8 Reserved2[2];\r
+ UINT32 Mxcsr;\r
+ UINT32 Mxcsr_Mask;\r
+ UINT8 St0Mm0[10];\r
+ UINT8 Reserved3[6];\r
+ UINT8 St1Mm1[10];\r
+ UINT8 Reserved4[6];\r
+ UINT8 St2Mm2[10];\r
+ UINT8 Reserved5[6];\r
+ UINT8 St3Mm3[10];\r
+ UINT8 Reserved6[6];\r
+ UINT8 St4Mm4[10];\r
+ UINT8 Reserved7[6];\r
+ UINT8 St5Mm5[10];\r
+ UINT8 Reserved8[6];\r
+ UINT8 St6Mm6[10];\r
+ UINT8 Reserved9[6];\r
+ UINT8 St7Mm7[10];\r
+ UINT8 Reserved10[6];\r
+ UINT8 Xmm0[16];\r
+ UINT8 Xmm1[16];\r
+ UINT8 Xmm2[16];\r
+ UINT8 Xmm3[16];\r
+ UINT8 Xmm4[16];\r
+ UINT8 Xmm5[16];\r
+ UINT8 Xmm6[16];\r
+ UINT8 Xmm7[16];\r
+ UINT8 Reserved11[14 * 16];\r
+} DEBUG_DATA_IA32_FX_SAVE_STATE;\r
+\r
+///\r
+/// IA-32 processor context definition\r
+///\r
+typedef struct {\r
+ DEBUG_DATA_IA32_FX_SAVE_STATE FxSaveState;\r
+ UINT32 Dr0;\r
+ UINT32 Dr1;\r
+ UINT32 Dr2;\r
+ UINT32 Dr3;\r
+ UINT32 Dr6;\r
+ UINT32 Dr7;\r
+ UINT32 Eflags;\r
+ UINT32 Ldtr;\r
+ UINT32 Tr;\r
+ UINT32 Gdtr[2];\r
+ UINT32 Idtr[2];\r
+ UINT32 Eip;\r
+ UINT32 Gs;\r
+ UINT32 Fs;\r
+ UINT32 Es;\r
+ UINT32 Ds;\r
+ UINT32 Cs;\r
+ UINT32 Ss;\r
+ UINT32 Cr0;\r
+ UINT32 Cr1; ///< Reserved\r
+ UINT32 Cr2;\r
+ UINT32 Cr3;\r
+ UINT32 Cr4;\r
+ UINT32 Edi;\r
+ UINT32 Esi;\r
+ UINT32 Ebp;\r
+ UINT32 Esp;\r
+ UINT32 Edx;\r
+ UINT32 Ecx;\r
+ UINT32 Ebx;\r
+ UINT32 Eax;\r
+} DEBUG_DATA_IA32_SYSTEM_CONTEXT;\r
+\r
+///\r
+/// IA32 GROUP register\r
+///\r
+typedef struct {\r
+ UINT16 Cs;\r
+ UINT16 Ds;\r
+ UINT16 Es;\r
+ UINT16 Fs;\r
+ UINT16 Gs;\r
+ UINT16 Ss;\r
+ UINT32 Eflags;\r
+ UINT32 Ebp;\r
+ UINT32 Eip;\r
+ UINT32 Esp;\r
+ UINT32 Eax;\r
+ UINT32 Ebx;\r
+ UINT32 Ecx;\r
+ UINT32 Edx;\r
+ UINT32 Esi;\r
+ UINT32 Edi;\r
+ UINT32 Dr0;\r
+ UINT32 Dr1;\r
+ UINT32 Dr2;\r
+ UINT32 Dr3;\r
+ UINT32 Dr6;\r
+ UINT32 Dr7;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_IA32;\r
+\r
+///\r
+/// IA32 Segment Limit GROUP register\r
+///\r
+typedef struct {\r
+ UINT32 CsLim;\r
+ UINT32 SsLim;\r
+ UINT32 GsLim;\r
+ UINT32 FsLim;\r
+ UINT32 EsLim;\r
+ UINT32 DsLim;\r
+ UINT32 LdtLim;\r
+ UINT32 TssLim;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_IA32;\r
+\r
+///\r
+/// IA32 Segment Base GROUP register\r
+///\r
+typedef struct {\r
+ UINT32 CsBas;\r
+ UINT32 SsBas;\r
+ UINT32 GsBas;\r
+ UINT32 FsBas;\r
+ UINT32 EsBas;\r
+ UINT32 DsBas;\r
+ UINT32 LdtBas;\r
+ UINT32 TssBas;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_IA32;\r
+\r
+#endif\r
--- /dev/null
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+# Module Name:\r
+#\r
+# AsmFuncs.S\r
+#\r
+# Abstract:\r
+#\r
+# Debug interrupt handle functions.\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+#include "DebugException.h"\r
+\r
+ASM_GLOBAL ASM_PFX(InterruptProcess)\r
+ASM_GLOBAL ASM_PFX(Exception0Handle)\r
+ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize)\r
+ASM_GLOBAL ASM_PFX(TimerInterruptHandle)\r
+ASM_GLOBAL ASM_PFX(CommonEntry)\r
+\r
+.data\r
+\r
+ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle)\r
+\r
+.text\r
+\r
+ASM_PFX(Exception0Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $0, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception1Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $1, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception2Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $2, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception3Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $3, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception4Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $4, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception5Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $5, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception6Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $6, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception7Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $7, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception8Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $8, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception9Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $9, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception10Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $10, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception11Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $11, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception12Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $12, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception13Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $13, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception14Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $14, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception15Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $15, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception16Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $16, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception17Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $17, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception18Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $18, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception19Handle):\r
+ cli\r
+ pushl %eax\r
+ mov $19, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+\r
+ASM_PFX(TimerInterruptHandle):\r
+ cli\r
+ pushl %eax\r
+ mov $32, %eax\r
+ jmp ASM_PFX(CommonEntry)\r
+\r
+\r
+ASM_PFX(CommonEntry):\r
+\r
+#---------------------------------------;\r
+# _CommonEntry ;\r
+#----------------------------------------------------------------------------;\r
+# The follow algorithm is used for the common interrupt routine.\r
+# Entry from each interrupt with a push eax and eax=interrupt number\r
+#\r
+# +---------------------+\r
+# + EFlags +\r
+# +---------------------+\r
+# + CS +\r
+# +---------------------+\r
+# + EIP +\r
+# +---------------------+\r
+# + Error Code +\r
+# +---------------------+\r
+# + EAX / Vector Number +\r
+# +---------------------+\r
+# + EBP +\r
+# +---------------------+ <-- EBP\r
+#\r
+\r
+# We need to determine if any extra data was pushed by the exception\r
+ cmpl $DEBUG_EXCEPT_DOUBLE_FAULT, %eax\r
+ je NoExtrPush\r
+ cmpl $DEBUG_EXCEPT_INVALID_TSS, %eax\r
+ je NoExtrPush\r
+ cmpl $DEBUG_EXCEPT_SEG_NOT_PRESENT, %eax\r
+ je NoExtrPush\r
+ cmpl $DEBUG_EXCEPT_STACK_FAULT, %eax\r
+ je NoExtrPush\r
+ cmpl $DEBUG_EXCEPT_GP_FAULT, %eax\r
+ je NoExtrPush\r
+ cmpl $DEBUG_EXCEPT_PAGE_FAULT, %eax\r
+ je NoExtrPush\r
+ cmpl $DEBUG_EXCEPT_ALIGNMENT_CHECK, %eax\r
+ je NoExtrPush\r
+\r
+ pushl (%esp)\r
+ movl $0, 4(%esp)\r
+\r
+NoExtrPush:\r
+\r
+ pushl %ebp\r
+ movl %esp,%ebp\r
+\r
+ #\r
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32\r
+ # is 16-byte aligned\r
+ #\r
+ andl $0xfffffff0,%esp\r
+ subl $12,%esp\r
+\r
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ pushl 0x4(%ebp)\r
+ pushl %ebx\r
+ pushl %ecx\r
+ pushl %edx\r
+ mov %eax, %ebx # save vector in ebx\r
+ leal 24(%ebp),%ecx\r
+ pushl %ecx # save original ESP\r
+ pushl (%ebp)\r
+ pushl %esi\r
+ pushl %edi\r
+\r
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ movl %cr4, %eax\r
+ orl $0x208,%eax\r
+ movl %eax, %cr4\r
+ pushl %eax\r
+ movl %cr3, %eax\r
+ pushl %eax\r
+ movl %cr2, %eax\r
+ pushl %eax\r
+ xorl %eax,%eax\r
+ pushl %eax\r
+ movl %cr0, %eax\r
+ pushl %eax\r
+\r
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+ movl %ss,%eax\r
+ pushl %eax\r
+ movzwl 16(%ebp), %eax\r
+ pushl %eax\r
+ movl %ds,%eax\r
+ pushl %eax\r
+ movl %es,%eax\r
+ pushl %eax\r
+ movl %fs,%eax\r
+ pushl %eax\r
+ movl %gs,%eax\r
+ pushl %eax\r
+\r
+## UINT32 Eip;\r
+ pushl 12(%ebp)\r
+\r
+## UINT32 Gdtr[2], Idtr[2];\r
+ subl $8,%esp\r
+ sidt (%esp)\r
+ subl $8,%esp\r
+ sgdt (%esp)\r
+\r
+## UINT32 Ldtr, Tr;\r
+ xorl %eax,%eax\r
+ strl %eax\r
+ pushl %eax\r
+ sldtl %eax\r
+ pushl %eax\r
+\r
+## UINT32 EFlags;\r
+ pushl 20(%ebp)\r
+\r
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ movl %dr7, %eax\r
+ pushl %eax\r
+## clear Dr7 while executing debugger itself\r
+ xorl %eax,%eax\r
+# movl %eax, %dr7\r
+\r
+ movl %dr6, %eax\r
+ pushl %eax\r
+## insure all status bits in dr6 are clear...\r
+ xorl %eax,%eax\r
+ movl %eax, %dr6\r
+\r
+ movl %dr3, %eax\r
+ pushl %eax\r
+ movl %dr2, %eax\r
+ pushl %eax\r
+ movl %dr1, %eax\r
+ pushl %eax\r
+ movl %dr0, %eax\r
+ pushl %eax\r
+\r
+## FX_SAVE_STATE_IA32 FxSaveState;\r
+ subl $512,%esp\r
+ movl %esp,%edi\r
+ .byte 0x0f, 0xae, 0x07 # fxsave [edi]\r
+\r
+## Clear Direction Flag\r
+ cld\r
+ \r
+## Prepare parameter and call C function\r
+ pushl %esp\r
+ pushl %ebx\r
+ call ASM_PFX(InterruptProcess)\r
+ addl $8,%esp\r
+\r
+## FX_SAVE_STATE_IA32 FxSaveState;\r
+ movl %esp,%esi\r
+ .byte 0x0f, 0xae, 0x0e # fxrstor [esi]\r
+ addl $512,%esp\r
+\r
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ popl %eax\r
+ movl %eax, %dr0\r
+ popl %eax\r
+ movl %eax, %dr1\r
+ popl %eax\r
+ movl %eax, %dr2\r
+ popl %eax\r
+ movl %eax, %dr3\r
+## skip restore of dr6. We cleared dr6 during the context save.\r
+ addl $4,%esp\r
+ popl %eax\r
+ movl %eax, %dr7\r
+\r
+## UINT32 EFlags;\r
+ popl 20(%ebp)\r
+\r
+## UINT32 Ldtr, Tr;\r
+## UINT32 Gdtr[2], Idtr[2];\r
+## Best not let anyone mess with these particular registers...\r
+ addl $24,%esp\r
+\r
+## UINT32 Eip;\r
+ pop 12(%ebp)\r
+\r
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+## NOTE - modified segment registers could hang the debugger... We\r
+## could attempt to insulate ourselves against this possibility,\r
+## but that poses risks as well.\r
+##\r
+ popl %gs\r
+ popl %fs\r
+ popl %es\r
+ popl %ds\r
+ popl 16(%ebp)\r
+ popl %ss\r
+\r
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ popl %eax\r
+ movl %eax, %cr0\r
+ addl $4,%esp # not for Cr1\r
+ popl %eax\r
+ movl %eax, %cr2\r
+ popl %eax\r
+ movl %eax, %cr3\r
+ popl %eax\r
+ movl %eax, %cr4\r
+\r
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
+ popl %edi\r
+ popl %esi\r
+ addl $4,%esp # not for ebp\r
+ addl $4,%esp # not for esp\r
+ popl %edx\r
+ popl %ecx\r
+ popl %ebx\r
+ popl %eax\r
+\r
+ movl %ebp,%esp\r
+ popl %ebp\r
+ addl $8,%esp # skip eax\r
+ iretl\r
+ \r
--- /dev/null
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution. The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php.\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+; Module Name:\r
+;\r
+; AsmFuncs.asm\r
+;\r
+; Abstract:\r
+;\r
+; Debug interrupt handle functions.\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+#include "DebugException.h"\r
+\r
+.686p\r
+.xmm\r
+.model flat,c\r
+\r
+;\r
+; InterruptProcess()\r
+;\r
+InterruptProcess PROTO C\r
+\r
+public Exception0Handle, TimerInterruptHandle, ExceptionStubHeaderSize\r
+\r
+.data\r
+\r
+ExceptionStubHeaderSize DW Exception1Handle - Exception0Handle\r
+CommonEntryAddr DD CommonEntry\r
+\r
+.code\r
+\r
+Exception0Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 0\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception1Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 1\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception2Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 2\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception3Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 3\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception4Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 4\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception5Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 5\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception6Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 6\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception7Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 7\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception8Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 8\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception9Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 9\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception10Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 10\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception11Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 11\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception12Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 12\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception13Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 13\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception14Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 14\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception15Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 15\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception16Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 16\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception17Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 17\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception18Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 18\r
+ jmp dword ptr [CommonEntryAddr]\r
+Exception19Handle:\r
+ cli\r
+ push eax\r
+ mov eax, 19\r
+ jmp dword ptr [CommonEntryAddr]\r
+\r
+TimerInterruptHandle:\r
+ cli\r
+ push eax\r
+ mov eax, 32\r
+ jmp dword ptr [CommonEntryAddr]\r
+\r
+CommonEntry:\r
+;\r
+; +---------------------+\r
+; + EFlags +\r
+; +---------------------+\r
+; + CS +\r
+; +---------------------+\r
+; + EIP +\r
+; +---------------------+\r
+; + Error Code +\r
+; +---------------------+\r
+; + EAX / Vector Number +\r
+; +---------------------+\r
+; + EBP +\r
+; +---------------------+ <-- EBP\r
+;\r
+ cmp eax, DEBUG_EXCEPT_DOUBLE_FAULT\r
+ je NoExtrPush\r
+ cmp eax, DEBUG_EXCEPT_INVALID_TSS\r
+ je NoExtrPush\r
+ cmp eax, DEBUG_EXCEPT_SEG_NOT_PRESENT\r
+ je NoExtrPush\r
+ cmp eax, DEBUG_EXCEPT_STACK_FAULT\r
+ je NoExtrPush\r
+ cmp eax, DEBUG_EXCEPT_GP_FAULT\r
+ je NoExtrPush\r
+ cmp eax, DEBUG_EXCEPT_PAGE_FAULT\r
+ je NoExtrPush\r
+ cmp eax, DEBUG_EXCEPT_ALIGNMENT_CHECK\r
+ je NoExtrPush\r
+\r
+ push [esp]\r
+ mov dword ptr [esp + 4], 0\r
+\r
+NoExtrPush:\r
+\r
+ push ebp\r
+ mov ebp, esp ; save esp in ebp\r
+ ;\r
+ ; Make stack 16-byte alignment to make sure save fxrstor later\r
+ ;\r
+ and esp, 0fffffff0h\r
+ sub esp, 12\r
+\r
+ ; store UINT32 Edi, Esi, Ebp, Ebx, Edx, Ecx, Eax;\r
+ push dword ptr [ebp + 4] ; original eax\r
+ push ebx\r
+ push ecx\r
+ push edx\r
+ mov ebx, eax ; save vector in ebx\r
+ mov eax, ebp\r
+ add eax, 4 * 6\r
+ push eax ; original ESP\r
+ push dword ptr [ebp] ; EBP\r
+ push esi\r
+ push edi\r
+\r
+ ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ ;; insure FXSAVE/FXRSTOR is enabled in CR4...\r
+ ;; ... while we're at it, make sure DE is also enabled...\r
+ mov eax, cr4\r
+ push eax ; push cr4 firstly\r
+ or eax, 208h\r
+ mov cr4, eax\r
+ mov eax, cr3\r
+ push eax\r
+ mov eax, cr2\r
+ push eax\r
+ push 0 ; cr0 will not saved???\r
+ mov eax, cr0\r
+ push eax\r
+\r
+ xor ecx, ecx\r
+ mov ecx, Ss\r
+ push ecx\r
+ mov ecx, Cs\r
+ push ecx\r
+ mov ecx, Ds\r
+ push ecx\r
+ mov ecx, Es\r
+ push ecx\r
+ mov ecx, Fs\r
+ push ecx\r
+ mov ecx, Gs\r
+ push ecx\r
+\r
+ ;; EIP\r
+ mov ecx, [ebp + 4 * 3] ; EIP\r
+ push ecx\r
+\r
+ ;; UINT32 Gdtr[2], Idtr[2];\r
+ sub esp, 8\r
+ sidt fword ptr [esp]\r
+ sub esp, 8\r
+ sgdt fword ptr [esp]\r
+\r
+ ;; UINT32 Ldtr, Tr;\r
+ xor eax, eax\r
+ str ax\r
+ push eax\r
+ sldt ax\r
+ push eax\r
+\r
+ ;; EFlags\r
+ mov ecx, [ebp + 4 * 5]\r
+ push ecx\r
+\r
+ ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ mov eax, dr7\r
+ push eax\r
+\r
+ ;; clear Dr7 while executing debugger itself\r
+ xor eax, eax\r
+ ;; mov dr7, eax\r
+\r
+ ;; Dr6\r
+ mov eax, dr6\r
+ push eax\r
+\r
+ ;; insure all status bits in dr6 are clear...\r
+ xor eax, eax\r
+ mov dr6, eax\r
+\r
+ mov eax, dr3\r
+ push eax\r
+ mov eax, dr2\r
+ push eax\r
+ mov eax, dr1\r
+ push eax\r
+ mov eax, dr0\r
+ push eax\r
+\r
+ ;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ sub esp, 512\r
+ mov edi, esp\r
+ db 0fh, 0aeh, 00000111y ;fxsave [edi]\r
+\r
+ ;; Clear Direction Flag\r
+ cld\r
+ \r
+ ; call the C interrupt process function\r
+ push esp ; Structure\r
+ push ebx ; vector\r
+ call InterruptProcess\r
+ add esp, 8\r
+\r
+ ;; FX_SAVE_STATE_IA32 FxSaveState;\r
+ mov esi, esp\r
+ db 0fh, 0aeh, 00001110y ; fxrstor [esi]\r
+ add esp, 512\r
+\r
+ ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ pop eax\r
+ mov dr0, eax\r
+ pop eax\r
+ mov dr1, eax\r
+ pop eax\r
+ mov dr2, eax\r
+ pop eax\r
+ mov dr3, eax\r
+ ;; skip restore of dr6. We cleared dr6 during the context save.\r
+ add esp, 4\r
+ pop eax\r
+ mov dr7, eax\r
+\r
+ ;; set EFlags\r
+ pop dword ptr [ebp + 4 * 5] ; set EFLAGS in stack\r
+\r
+ ;; UINT32 Ldtr, Tr;\r
+ ;; UINT32 Gdtr[2], Idtr[2];\r
+ ;; Best not let anyone mess with these particular registers...\r
+ add esp, 24\r
+\r
+ ;; UINT32 Eip;\r
+ pop dword ptr [ebp + 4 * 3] ; set EIP in stack\r
+\r
+ ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;\r
+ ;; NOTE - modified segment registers could hang the debugger... We\r
+ ;; could attempt to insulate ourselves against this possibility,\r
+ ;; but that poses risks as well.\r
+ ;;\r
+ pop gs\r
+ pop fs\r
+ pop es\r
+ pop ds\r
+ pop dword ptr [ebp + 4 * 4] ; set CS in stack\r
+ pop ss\r
+\r
+ ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ pop eax\r
+ mov cr0, eax\r
+ add esp, 4 ; skip for Cr1\r
+ pop eax\r
+ mov cr2, eax\r
+ pop eax\r
+ mov cr3, eax\r
+ pop eax\r
+ mov cr4, eax\r
+\r
+ ;; restore general register\r
+ pop edi\r
+ pop esi\r
+ pop dword ptr [ebp] ; save updated ebp\r
+ pop dword ptr [ebp + 4] ; save updated esp\r
+ pop edx\r
+ pop ecx\r
+ pop ebx\r
+ pop eax\r
+\r
+ mov esp, ebp\r
+ pop ebp ; restore ebp maybe updated\r
+ pop esp ; restore esp maybe updated\r
+ sub esp, 4 * 3 ; restore interupt pushced stack\r
+\r
+ iretd\r
+\r
+END\r
--- /dev/null
+/** @file\r
+ Exception defintions.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DEBUG_EXCEPTION_H_\r
+#define _DEBUG_EXCEPTION_H_\r
+\r
+#define DEBUG_EXCEPT_DIVIDE_ERROR 0\r
+#define DEBUG_EXCEPT_DEBUG 1\r
+#define DEBUG_EXCEPT_NMI 2\r
+#define DEBUG_EXCEPT_BREAKPOINT 3\r
+#define DEBUG_EXCEPT_OVERFLOW 4\r
+#define DEBUG_EXCEPT_BOUND 5\r
+#define DEBUG_EXCEPT_INVALID_OPCODE 6\r
+#define DEBUG_EXCEPT_DOUBLE_FAULT 8\r
+#define DEBUG_EXCEPT_INVALID_TSS 10\r
+#define DEBUG_EXCEPT_SEG_NOT_PRESENT 11\r
+#define DEBUG_EXCEPT_STACK_FAULT 12\r
+#define DEBUG_EXCEPT_GP_FAULT 13\r
+#define DEBUG_EXCEPT_PAGE_FAULT 14\r
+#define DEBUG_EXCEPT_FP_ERROR 16\r
+#define DEBUG_EXCEPT_ALIGNMENT_CHECK 17\r
+#define DEBUG_EXCEPT_MACHINE_CHECK 18\r
+#define DEBUG_EXCEPT_SIMD 19\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Supporting functions for x64 architecture.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+\r
+/**\r
+ Read the offset of FP / MMX / XMM registers by register index.\r
+\r
+ @param[in] Index Register index.\r
+ @param[out] Width Register width returned.\r
+\r
+ @return Offset in register address range.\r
+\r
+**/\r
+UINT16\r
+ArchReadFxStatOffset (\r
+ IN UINT8 Index,\r
+ OUT UINT8 *Width\r
+ )\r
+{\r
+ if (Index < SOFT_DEBUGGER_REGISTER_ST0) {\r
+ switch (Index) {\r
+ case SOFT_DEBUGGER_REGISTER_FP_FCW:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Fcw);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_FSW:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Fsw);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_FTW:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Ftw);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_OPCODE:\r
+ *Width = (UINT8) sizeof (UINT16);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Opcode);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_EIP:\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Rip);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, DataOffset);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR:\r
+ *Width = (UINT8) sizeof (UINT32);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Mxcsr);\r
+\r
+ case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:\r
+ *Width = (UINT8) sizeof (UINT32);\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, Mxcsr_Mask);\r
+\r
+ default:\r
+ return (UINT16) (-1);\r
+ }\r
+ }\r
+\r
+ if (Index < SOFT_DEBUGGER_REGISTER_XMM0) {\r
+ *Width = 10;\r
+ } else if (Index < SOFT_DEBUGGER_REGISTER_MM0 ) {\r
+ *Width = 16;\r
+ } else {\r
+ *Width = 8;\r
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
+ }\r
+\r
+ return OFFSET_OF(DEBUG_DATA_X64_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;\r
+}\r
+\r
+/**\r
+ Write specified register into save CPU context.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Index Register index value.\r
+ @param[in] Offset Offset in register address range\r
+ @param[in] Width Data width to read.\r
+ @param[in] RegisterBuffer Pointer to input buffer with data.\r
+\r
+**/\r
+VOID\r
+ArchWriteRegisterBuffer (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 Index,\r
+ IN UINT8 Offset,\r
+ IN UINT8 Width,\r
+ IN UINT8 *RegisterBuffer\r
+ )\r
+{\r
+ UINT8 *Buffer;\r
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_X64_FX_SAVE_STATE) + Index * 8;\r
+ } else {\r
+ //\r
+ // If it is MMX register, adjust its index position\r
+ //\r
+ if (Index >= SOFT_DEBUGGER_REGISTER_MM0) {\r
+ Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;\r
+ }\r
+\r
+ //\r
+ // FPU/MMX/XMM registers\r
+ //\r
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, &Width);\r
+ }\r
+\r
+ CopyMem (Buffer + Offset, RegisterBuffer, Width);\r
+}\r
+\r
+/**\r
+ Read register value from saved CPU context.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] Index Register index value.\r
+ @param[in] Offset Offset in register address range\r
+ @param[in] Width Data width to read.\r
+\r
+ @return The address of register value.\r
+\r
+**/\r
+UINT8 *\r
+ArchReadRegisterBuffer (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 Index,\r
+ IN UINT8 Offset,\r
+ IN UINT8 *Width\r
+ )\r
+{\r
+ UINT8 *Buffer;\r
+\r
+ if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {\r
+ Buffer = (UINT8 *) CpuContext + sizeof (DEBUG_DATA_X64_FX_SAVE_STATE) + Index * 8;\r
+ if (*Width == 0) {\r
+ *Width = (UINT8) sizeof (UINTN);\r
+ }\r
+ } else {\r
+ //\r
+ // FPU/MMX/XMM registers\r
+ //\r
+ Buffer = (UINT8 *) CpuContext + ArchReadFxStatOffset (Index, Width);\r
+ }\r
+\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Read group register of common registers.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroup Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroup (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP *RegisterGroup\r
+ )\r
+{\r
+ RegisterGroup->Cs = (UINT16) CpuContext->Cs;\r
+ RegisterGroup->Ds = (UINT16) CpuContext->Ds;\r
+ RegisterGroup->Es = (UINT16) CpuContext->Es;\r
+ RegisterGroup->Fs = (UINT16) CpuContext->Fs;\r
+ RegisterGroup->Gs = (UINT16) CpuContext->Gs;\r
+ RegisterGroup->Ss = (UINT16) CpuContext->Ss;\r
+ RegisterGroup->Eflags = (UINT32) CpuContext->Eflags;\r
+ RegisterGroup->Rbp = CpuContext->Rbp;\r
+ RegisterGroup->Eip = CpuContext->Eip;\r
+ RegisterGroup->Rsp = CpuContext->Rsp;\r
+ RegisterGroup->Eax = CpuContext->Rax;\r
+ RegisterGroup->Rbx = CpuContext->Rbx;\r
+ RegisterGroup->Rcx = CpuContext->Rcx;\r
+ RegisterGroup->Rdx = CpuContext->Rdx;\r
+ RegisterGroup->Rsi = CpuContext->Rsi;\r
+ RegisterGroup->Rdi = CpuContext->Rdi;\r
+ RegisterGroup->R8 = CpuContext->R8;\r
+ RegisterGroup->R9 = CpuContext->R9;\r
+ RegisterGroup->R10 = CpuContext->R10;\r
+ RegisterGroup->R11 = CpuContext->R11;\r
+ RegisterGroup->R12 = CpuContext->R12;\r
+ RegisterGroup->R13 = CpuContext->R13;\r
+ RegisterGroup->R14 = CpuContext->R14;\r
+ RegisterGroup->R15 = CpuContext->R15;\r
+ RegisterGroup->Dr0 = CpuContext->Dr0;\r
+ RegisterGroup->Dr1 = CpuContext->Dr1;\r
+ RegisterGroup->Dr2 = CpuContext->Dr2;\r
+ RegisterGroup->Dr3 = CpuContext->Dr3;\r
+ RegisterGroup->Dr6 = CpuContext->Dr6;\r
+ RegisterGroup->Dr7 = CpuContext->Dr7;\r
+ RegisterGroup->Cr0 = CpuContext->Cr0;\r
+ RegisterGroup->Cr2 = CpuContext->Cr2;\r
+ RegisterGroup->Cr3 = CpuContext->Cr3;\r
+ RegisterGroup->Cr4 = CpuContext->Cr4;\r
+ RegisterGroup->Cr8 = CpuContext->Cr8;\r
+\r
+ CopyMem ((UINT8 *) &RegisterGroup->Xmm0[0], (UINT8 *) &CpuContext->FxSaveState.Xmm0[0], 16 * 10);\r
+}\r
+\r
+/**\r
+ Initialize IDT entries to support source level debug.\r
+\r
+**/\r
+VOID\r
+InitializeDebugIdt (\r
+ VOID\r
+ )\r
+{\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;\r
+ UINTN InterruptHandler;\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+ UINTN Index;\r
+ UINT16 CodeSegment;\r
+\r
+ AsmReadIdtr (&IdtDescriptor);\r
+\r
+ //\r
+ // Use current CS as the segment selector of interrupt gate in IDT\r
+ //\r
+ CodeSegment = AsmReadCs ();\r
+\r
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+ for (Index = 0; Index < 20; Index ++) {\r
+ if ((PcdGet32 (PcdExceptionsIgnoredByDebugger) & (1 << Index)) != 0) {\r
+ //\r
+ // If the exception is masked to be reserved, skip it\r
+ //\r
+ continue;\r
+ }\r
+ InterruptHandler = (UINTN)&Exception0Handle + Index * ExceptionStubHeaderSize;\r
+ IdtEntry[Index].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;\r
+ IdtEntry[Index].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
+ IdtEntry[Index].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);\r
+ IdtEntry[Index].Bits.Selector = CodeSegment;\r
+ IdtEntry[Index].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+ }\r
+\r
+ InterruptHandler = (UINTN) &TimerInterruptHandle;\r
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;\r
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)InterruptHandler >> 16);\r
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);\r
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.Selector = CodeSegment;\r
+ IdtEntry[DEBUG_TIMER_VECTOR].Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+}\r
--- /dev/null
+/** @file\r
+ X64 specific defintions for debug agent library instance.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _ARCH_DEBUG_SUPPORT_H_\r
+#define _ARCH_DEBUG_SUPPORT_H_\r
+\r
+#include "ArchRegisters.h"\r
+#include "TransferProtocol.h"\r
+\r
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP;\r
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM;\r
+typedef DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_X64 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE;\r
+\r
+#define DEBUG_SW_BREAKPOINT_SYMBOL 0xcc\r
+\r
+#define DEBUG_ARCH_SYMBOL DEBUG_DATA_BREAK_CPU_ARCH_X64\r
+\r
+typedef DEBUG_DATA_X64_SYSTEM_CONTEXT DEBUG_CPU_CONTEXT;\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ x64 Group registers read support functions.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DebugAgent.h"\r
+\r
+/**\r
+ Read segment selector by register index.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterIndex Register Index.\r
+\r
+ @return Value of segment selector.\r
+\r
+**/\r
+UINT64\r
+ReadRegisterSelectorByIndex (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 RegisterIndex\r
+ )\r
+{\r
+ IA32_DESCRIPTOR *Ia32Descriptor;\r
+ IA32_GDT *Ia32Gdt;\r
+ UINT16 Selector;\r
+ UINT32 Data32;\r
+\r
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;\r
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);\r
+\r
+ Selector = 0;\r
+\r
+ switch (RegisterIndex) {\r
+ case SOFT_DEBUGGER_REGISTER_CSAS:\r
+ Selector = (UINT16) CpuContext->Cs;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_SSAS:\r
+ Selector = (UINT16) CpuContext->Ss;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_GSAS:\r
+ Selector = (UINT16) CpuContext->Gs;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_FSAS:\r
+ Selector = (UINT16) CpuContext->Fs;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_ESAS:\r
+ Selector = (UINT16) CpuContext->Es;\r
+ break;\r
+ case SOFT_DEBUGGER_REGISTER_DSAS:\r
+ Selector = (UINT16) CpuContext->Ds;\r
+ case SOFT_DEBUGGER_REGISTER_LDTAS:\r
+ case SOFT_DEBUGGER_REGISTER_TSSAS:\r
+ return 0x00820000;\r
+ break;\r
+ }\r
+\r
+ Data32 = (UINT32) RShiftU64 (Ia32Gdt[Selector / 8].Uint64, 24);\r
+ return (Data32 & (UINT32)(~0xff)) | Selector;\r
+\r
+}\r
+\r
+/**\r
+ Read group register of Segment Base.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroupSegBase Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroupSegBase (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *RegisterGroupSegBase\r
+ )\r
+{\r
+ IA32_DESCRIPTOR *Ia32Descriptor;\r
+ IA32_GDT *Ia32Gdt;\r
+ UINTN Index;\r
+\r
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;\r
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);\r
+\r
+ Index = CpuContext->Cs / 8;\r
+ RegisterGroupSegBase->CsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Ss / 8;\r
+ RegisterGroupSegBase->SsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Gs / 8;\r
+ RegisterGroupSegBase->GsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Fs / 8;\r
+ RegisterGroupSegBase->FsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Es / 8;\r
+ RegisterGroupSegBase->EsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+ Index = CpuContext->Ds / 8;\r
+ RegisterGroupSegBase->DsBas = (Ia32Gdt[Index].Bits.BaseLow) + (Ia32Gdt[Index].Bits.BaseMid << 16) + (Ia32Gdt[Index].Bits.BaseMid << 24);\r
+\r
+ RegisterGroupSegBase->LdtBas = 0;\r
+ RegisterGroupSegBase->TssBas = 0;\r
+}\r
+\r
+/**\r
+ Read group register of Segment Limit.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] RegisterGroupSegLim Pointer to Group registers.\r
+\r
+**/\r
+VOID\r
+ReadRegisterGroupSegLim (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *RegisterGroupSegLim\r
+ )\r
+{\r
+ IA32_DESCRIPTOR *Ia32Descriptor;\r
+ IA32_GDT *Ia32Gdt;\r
+ UINTN Index;\r
+\r
+ Ia32Descriptor = (IA32_DESCRIPTOR *) CpuContext->Gdtr;\r
+ Ia32Gdt = (IA32_GDT *) (Ia32Descriptor->Base);\r
+\r
+ Index = CpuContext->Cs / 8;\r
+ RegisterGroupSegLim->CsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->CsLim = (RegisterGroupSegLim->CsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Ss / 8;\r
+ RegisterGroupSegLim->SsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->SsLim = (RegisterGroupSegLim->SsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Gs / 8;\r
+ RegisterGroupSegLim->GsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->GsLim = (RegisterGroupSegLim->GsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Fs / 8;\r
+ RegisterGroupSegLim->FsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->FsLim = (RegisterGroupSegLim->FsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Es / 8;\r
+ RegisterGroupSegLim->EsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->EsLim = (RegisterGroupSegLim->EsLim << 12) | 0xfff;\r
+ }\r
+\r
+ Index = CpuContext->Ds / 8;\r
+ RegisterGroupSegLim->DsLim = Ia32Gdt[Index].Bits.LimitLow + (Ia32Gdt[Index].Bits.LimitHigh << 16);\r
+ if (Ia32Gdt[Index].Bits.Granularity == 1) {\r
+ RegisterGroupSegLim->DsLim = (RegisterGroupSegLim->DsLim << 12) | 0xfff;\r
+ }\r
+\r
+ RegisterGroupSegLim->LdtLim = 0xffff;\r
+ RegisterGroupSegLim->TssLim = 0xffff;\r
+}\r
+\r
+/**\r
+ Read group register by group index.\r
+\r
+ @param[in] CpuContext Pointer to saved CPU context.\r
+ @param[in] GroupIndex Group Index.\r
+\r
+ @retval RETURN_SUCCESS Read successfully.\r
+ @retval RETURN_NOT_SUPPORTED Group index cannot be supported.\r
+\r
+**/\r
+RETURN_STATUS\r
+ArchReadRegisterGroup (\r
+ IN DEBUG_CPU_CONTEXT *CpuContext,\r
+ IN UINT8 GroupIndex\r
+ )\r
+{\r
+ UINTN DataN;\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP RegisterGroup;\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM RegisterGroupBasLim;\r
+ DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64 RegisterGroupBases64;\r
+\r
+ switch (GroupIndex) {\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT64:\r
+ ReadRegisterGroup (CpuContext, &RegisterGroup);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BAS_LIM64:\r
+ DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);\r
+ RegisterGroupBasLim.IdtLim = DataN;\r
+ DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);\r
+ RegisterGroupBasLim.GdtLim = DataN;\r
+ DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);\r
+ DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], sizeof (UINTN) * 8 - 16);\r
+ RegisterGroupBasLim.IdtBas = DataN;\r
+ DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);\r
+ DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], sizeof (UINTN) * 8 - 16);\r
+ RegisterGroupBasLim.GdtBas = DataN;\r
+\r
+ ReadRegisterGroupSegLim (CpuContext, (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM *) &RegisterGroupBasLim.CsLim);\r
+ ReadRegisterGroupSegBase (CpuContext, (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE *) &RegisterGroupBasLim.CsBas);\r
+\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupBasLim, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_GP2_64:\r
+ ReadRegisterGroup (CpuContext, &RegisterGroup);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Eflags, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP2));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_GP64:\r
+ ReadRegisterGroup (CpuContext, &RegisterGroup);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Eax, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_DR64:\r
+ ReadRegisterGroup (CpuContext, &RegisterGroup);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr0, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_DR));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_SEGMENT_BASES64:\r
+ RegisterGroupBases64.Ldtr = (UINT16) CpuContext->Ldtr;\r
+ RegisterGroupBases64.Tr = (UINT16) CpuContext->Tr;\r
+\r
+ RegisterGroupBases64.Csas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_CSAS);\r
+ RegisterGroupBases64.Ssas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_SSAS);\r
+ RegisterGroupBases64.Gsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_GSAS);\r
+ RegisterGroupBases64.Fsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_FSAS);\r
+ RegisterGroupBases64.Esas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_ESAS);\r
+ RegisterGroupBases64.Dsas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_DSAS);\r
+ RegisterGroupBases64.Ldtas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_LDTAS);\r
+ RegisterGroupBases64.Tssas = ReadRegisterSelectorByIndex (CpuContext, SOFT_DEBUGGER_REGISTER_TSSAS);\r
+\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroupBases64, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_CR64:\r
+ ReadRegisterGroup (CpuContext, &RegisterGroup);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr7 + 8, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_CR));\r
+ break;\r
+\r
+ case SOFT_DEBUGGER_REGISTER_GROUP_XMM64:\r
+ ReadRegisterGroup (CpuContext, &RegisterGroup);\r
+ SendDataResponsePacket (CpuContext, (UINT8 *) &RegisterGroup.Dr7 + 8 * 6, (UINT16) sizeof (DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_XMM));\r
+ break;\r
+\r
+ default:\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ X64 register defintions needed by debug transfer protocol.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _ARCH_REGISTERS_H_\r
+#define _ARCH_REGISTERS_H_\r
+\r
+///\r
+/// FXSAVE_STATE (promoted operation)\r
+/// FP / MMX / XMM registers (see fxrstor instruction definition)\r
+///\r
+typedef struct {\r
+ UINT16 Fcw;\r
+ UINT16 Fsw;\r
+ UINT16 Ftw;\r
+ UINT16 Opcode;\r
+ UINT64 Rip;\r
+ UINT64 DataOffset;\r
+ UINT32 Mxcsr;\r
+ UINT32 Mxcsr_Mask;\r
+ UINT8 St0Mm0[10];\r
+ UINT8 Reserved2[6];\r
+ UINT8 St1Mm1[10];\r
+ UINT8 Reserved3[6];\r
+ UINT8 St2Mm2[10];\r
+ UINT8 Reserved4[6];\r
+ UINT8 St3Mm3[10];\r
+ UINT8 Reserved5[6];\r
+ UINT8 St4Mm4[10];\r
+ UINT8 Reserved6[6];\r
+ UINT8 St5Mm5[10];\r
+ UINT8 Reserved7[6];\r
+ UINT8 St6Mm6[10];\r
+ UINT8 Reserved8[6];\r
+ UINT8 St7Mm7[10];\r
+ UINT8 Reserved9[6];\r
+ UINT8 Xmm0[16];\r
+ UINT8 Xmm1[16];\r
+ UINT8 Xmm2[16];\r
+ UINT8 Xmm3[16];\r
+ UINT8 Xmm4[16];\r
+ UINT8 Xmm5[16];\r
+ UINT8 Xmm6[16];\r
+ UINT8 Xmm7[16];\r
+ UINT8 Xmm8[16];\r
+ UINT8 Xmm9[16];\r
+ UINT8 Xmm10[16];\r
+ UINT8 Xmm11[16];\r
+ UINT8 Xmm12[16];\r
+ UINT8 Xmm13[16];\r
+ UINT8 Xmm14[16];\r
+ UINT8 Xmm15[16];\r
+ UINT8 Reserved11[6 * 16];\r
+} DEBUG_DATA_X64_FX_SAVE_STATE;\r
+\r
+///\r
+/// x64 processor context definition\r
+///\r
+typedef struct {\r
+ DEBUG_DATA_X64_FX_SAVE_STATE FxSaveState;\r
+ UINT64 Dr0;\r
+ UINT64 Dr1;\r
+ UINT64 Dr2;\r
+ UINT64 Dr3;\r
+ UINT64 Dr6;\r
+ UINT64 Dr7;\r
+ UINT64 Eflags;\r
+ UINT64 Ldtr;\r
+ UINT64 Tr;\r
+ UINT64 Gdtr[2];\r
+ UINT64 Idtr[2];\r
+ UINT64 Eip;\r
+ UINT64 Gs;\r
+ UINT64 Fs;\r
+ UINT64 Es;\r
+ UINT64 Ds;\r
+ UINT64 Cs;\r
+ UINT64 Ss;\r
+ UINT64 Cr0;\r
+ UINT64 Cr1; /* Reserved */\r
+ UINT64 Cr2;\r
+ UINT64 Cr3;\r
+ UINT64 Cr4;\r
+ UINT64 Rdi;\r
+ UINT64 Rsi;\r
+ UINT64 Rbp;\r
+ UINT64 Rsp;\r
+ UINT64 Rdx;\r
+ UINT64 Rcx;\r
+ UINT64 Rbx;\r
+ UINT64 Rax;\r
+ UINT64 Cr8;\r
+ UINT64 R8;\r
+ UINT64 R9;\r
+ UINT64 R10;\r
+ UINT64 R11;\r
+ UINT64 R12;\r
+ UINT64 R13;\r
+ UINT64 R14;\r
+ UINT64 R15;\r
+} DEBUG_DATA_X64_SYSTEM_CONTEXT;\r
+\r
+\r
+///\r
+/// x64 GROUP register\r
+///\r
+typedef struct {\r
+ UINT16 Cs;\r
+ UINT16 Ds;\r
+ UINT16 Es;\r
+ UINT16 Fs;\r
+ UINT16 Gs;\r
+ UINT16 Ss;\r
+ UINT32 Eflags;\r
+ UINT64 Rbp;\r
+ UINT64 Eip;\r
+ UINT64 Rsp;\r
+ UINT64 Eax;\r
+ UINT64 Rbx;\r
+ UINT64 Rcx;\r
+ UINT64 Rdx;\r
+ UINT64 Rsi;\r
+ UINT64 Rdi;\r
+ UINT64 R8;\r
+ UINT64 R9;\r
+ UINT64 R10;\r
+ UINT64 R11;\r
+ UINT64 R12;\r
+ UINT64 R13;\r
+ UINT64 R14;\r
+ UINT64 R15;\r
+ UINT64 Dr0;\r
+ UINT64 Dr1;\r
+ UINT64 Dr2;\r
+ UINT64 Dr3;\r
+ UINT64 Dr6;\r
+ UINT64 Dr7;\r
+ UINT64 Cr0;\r
+ UINT64 Cr2;\r
+ UINT64 Cr3;\r
+ UINT64 Cr4;\r
+ UINT64 Cr8;\r
+ UINT8 Xmm0[16];\r
+ UINT8 Xmm1[16];\r
+ UINT8 Xmm2[16];\r
+ UINT8 Xmm3[16];\r
+ UINT8 Xmm4[16];\r
+ UINT8 Xmm5[16];\r
+ UINT8 Xmm6[16];\r
+ UINT8 Xmm7[16];\r
+ UINT8 Xmm8[16];\r
+ UINT8 Xmm9[16];\r
+ UINT8 Xmm10[16];\r
+ UINT8 Xmm11[16];\r
+ UINT8 Xmm12[16];\r
+ UINT8 Xmm13[16];\r
+ UINT8 Xmm14[16];\r
+ UINT8 Xmm15[16];\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_X64;\r
+\r
+///\r
+/// x64 Segment Limit GROUP register\r
+///\r
+typedef struct {\r
+ UINT64 CsLim;\r
+ UINT64 SsLim;\r
+ UINT64 GsLim;\r
+ UINT64 FsLim;\r
+ UINT64 EsLim;\r
+ UINT64 DsLim;\r
+ UINT64 LdtLim;\r
+ UINT64 TssLim;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM_X64;\r
+\r
+///\r
+/// x64 Segment Base GROUP register\r
+///\r
+typedef struct {\r
+ UINT64 CsBas;\r
+ UINT64 SsBas;\r
+ UINT64 GsBas;\r
+ UINT64 FsBas;\r
+ UINT64 EsBas;\r
+ UINT64 DsBas;\r
+ UINT64 LdtBas;\r
+ UINT64 TssBas;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE_X64;\r
+\r
+///\r
+/// x64 Segment Base/Limit GROUP register\r
+///\r
+typedef struct {\r
+ UINT64 IdtBas;\r
+ UINT64 IdtLim;\r
+ UINT64 GdtBas;\r
+ UINT64 GdtLim;\r
+ UINT64 CsLim;\r
+ UINT64 SsLim;\r
+ UINT64 GsLim;\r
+ UINT64 FsLim;\r
+ UINT64 EsLim;\r
+ UINT64 DsLim;\r
+ UINT64 LdtLim;\r
+ UINT64 TssLim;\r
+ UINT64 CsBas;\r
+ UINT64 SsBas;\r
+ UINT64 GsBas;\r
+ UINT64 FsBas;\r
+ UINT64 EsBas;\r
+ UINT64 DsBas;\r
+ UINT64 LdtBas;\r
+ UINT64 TssBas;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BAS_LIM;\r
+\r
+///\r
+/// x64 register GROUP register\r
+///\r
+typedef struct {\r
+ UINT32 Eflags;\r
+ UINT64 Rbp;\r
+ UINT64 Eip;\r
+ UINT64 Rsp;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP2;\r
+\r
+///\r
+/// x64 general register GROUP register\r
+///\r
+typedef struct {\r
+ UINT64 Eax;\r
+ UINT64 Rbx;\r
+ UINT64 Rcx;\r
+ UINT64 Rdx;\r
+ UINT64 Rsi;\r
+ UINT64 Rdi;\r
+ UINT64 R8;\r
+ UINT64 R9;\r
+ UINT64 R10;\r
+ UINT64 R11;\r
+ UINT64 R12;\r
+ UINT64 R13;\r
+ UINT64 R14;\r
+ UINT64 R15;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_GP;\r
+\r
+///\r
+/// x64 Segment GROUP register\r
+///\r
+typedef struct {\r
+ UINT16 Cs;\r
+ UINT16 Ds;\r
+ UINT16 Es;\r
+ UINT16 Fs;\r
+ UINT16 Gs;\r
+ UINT16 Ss;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT;\r
+\r
+///\r
+/// x64 Debug Register GROUP register\r
+///\r
+typedef struct {\r
+ UINT64 Dr0;\r
+ UINT64 Dr1;\r
+ UINT64 Dr2;\r
+ UINT64 Dr3;\r
+ UINT64 Dr6;\r
+ UINT64 Dr7;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_DR;\r
+\r
+///\r
+/// x64 Control Register GROUP register\r
+///\r
+typedef struct {\r
+ UINT64 Cr0;\r
+ UINT64 Cr2;\r
+ UINT64 Cr3;\r
+ UINT64 Cr4;\r
+ UINT64 Cr8;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_CR;\r
+\r
+///\r
+/// x64 XMM Register GROUP register\r
+///\r
+typedef struct {\r
+ UINT8 Xmm0[16];\r
+ UINT8 Xmm1[16];\r
+ UINT8 Xmm2[16];\r
+ UINT8 Xmm3[16];\r
+ UINT8 Xmm4[16];\r
+ UINT8 Xmm5[16];\r
+ UINT8 Xmm6[16];\r
+ UINT8 Xmm7[16];\r
+ UINT8 Xmm8[16];\r
+ UINT8 Xmm9[16];\r
+ UINT8 Xmm10[16];\r
+ UINT8 Xmm11[16];\r
+ UINT8 Xmm12[16];\r
+ UINT8 Xmm13[16];\r
+ UINT8 Xmm14[16];\r
+ UINT8 Xmm15[16];\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_XMM;\r
+\r
+///\r
+/// x64 Segment Base GROUP register\r
+///\r
+typedef struct {\r
+ UINT16 Ldtr;\r
+ UINT16 Tr;\r
+ UINT64 Csas;\r
+ UINT64 Ssas;\r
+ UINT64 Gsas;\r
+ UINT64 Fsas;\r
+ UINT64 Esas;\r
+ UINT64 Dsas;\r
+ UINT64 Ldtas;\r
+ UINT64 Tssas;\r
+} DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGMENT_BASES_X64;\r
+\r
+\r
+#endif\r
--- /dev/null
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+# Module Name:\r
+#\r
+# AsmFuncs.S\r
+#\r
+# Abstract:\r
+#\r
+# Debug interrupt handle functions.\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+#include "DebugException.h"\r
+\r
+ASM_GLOBAL ASM_PFX(InterruptProcess)\r
+\r
+ASM_GLOBAL ASM_PFX(Exception0Handle)\r
+ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize)\r
+ASM_GLOBAL ASM_PFX(TimerInterruptHandle)\r
+ASM_GLOBAL ASM_PFX(CommonEntry)\r
+\r
+.data
+\r
+ASM_PFX(ExceptionStubHeaderSize): .word ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle)
+\r
+\r
+.text\r
+\r
+ASM_PFX(Exception0Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $0, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception1Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $1, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception2Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $2, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception3Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $3, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception4Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $4, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception5Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $5, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception6Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $6, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception7Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $7, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception8Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $8, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception9Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $9, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception10Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $10, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception11Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $11, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception12Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $12, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception13Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $13, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception14Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $14, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception15Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $15, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception16Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $16, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception17Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $17, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception18Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $18, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+ASM_PFX(Exception19Handle):\r
+ cli\r
+ pushq %rcx\r
+ mov $19, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+\r
+ASM_PFX(TimerInterruptHandle):\r
+ cli\r
+ pushq %rcx\r
+ mov $32, %rcx\r
+ jmp ASM_PFX(CommonEntry)\r
+\r
+\r
+ASM_PFX(CommonEntry):\r
+\r
+#---------------------------------------;\r
+# CommonInterruptEntry ;\r
+#---------------------------------------;\r
+# The follow algorithm is used for the common interrupt routine.\r
+\r
+#\r
+# +---------------------+ <-- 16-byte aligned ensured by processor\r
+# + Old SS +\r
+# +---------------------+\r
+# + Old RSP +\r
+# +---------------------+\r
+# + RFlags +\r
+# +---------------------+\r
+# + CS +\r
+# +---------------------+\r
+# + RIP +\r
+# +---------------------+\r
+# + Error Code +\r
+# +---------------------+\r
+# + RCX / Vector Number +\r
+# +---------------------+\r
+# + RBP +\r
+# +---------------------+ <-- RBP, 16-byte aligned\r
+#\r
+\r
+# We need to determine if any extra data was pushed by the exception\r
+ cmpq $DEBUG_EXCEPT_DOUBLE_FAULT, %rcx\r
+ je NoExtrPush\r
+ cmpq $DEBUG_EXCEPT_INVALID_TSS, %rcx\r
+ je NoExtrPush\r
+ cmpq $DEBUG_EXCEPT_SEG_NOT_PRESENT, %rcx\r
+ je NoExtrPush\r
+ cmpq $DEBUG_EXCEPT_STACK_FAULT, %rcx\r
+ je NoExtrPush\r
+ cmpq $DEBUG_EXCEPT_GP_FAULT, %rcx\r
+ je NoExtrPush\r
+ cmpq $DEBUG_EXCEPT_PAGE_FAULT, %rcx\r
+ je NoExtrPush\r
+ cmpq $DEBUG_EXCEPT_ALIGNMENT_CHECK, %rcx\r
+ je NoExtrPush\r
+\r
+ pushq (%rsp)\r
+ movq $0, 8(%rsp)\r
+\r
+NoExtrPush:\r
+ #\r
+ # All interrupt handlers are invoked through interrupt gates, so\r
+ # IF flag automatically cleared at the entry point\r
+ pushq %rbp\r
+ movq %rsp, %rbp\r
+\r
+ #\r
+ # Since here the stack pointer is 16-byte aligned, so\r
+ # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64\r
+ # is 16-byte aligned\r
+ #\r
+\r
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ pushq %r15\r
+ pushq %r14\r
+ pushq %r13\r
+ pushq %r12\r
+ pushq %r11\r
+ pushq %r10\r
+ pushq %r9\r
+ pushq %r8\r
+\r
+ movq %cr8, %r8\r
+ pushq %r8\r
+\r
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+ pushq %rax\r
+ pushq %rbx\r
+ pushq 8(%rbp) # original rcx\r
+ pushq %rdx\r
+ pushq 48(%rbp) # original rsp\r
+ pushq (%rbp) # original rbp\r
+ pushq %rsi\r
+ pushq %rdi\r
+\r
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ movq %cr4, %rax\r
+ orq $0x208, %rax\r
+ movq %rax, %cr4\r
+ pushq %rax\r
+ movq %cr3, %rax\r
+ pushq %rax\r
+ movq %cr2, %rax\r
+ pushq %rax\r
+ xorq %rax, %rax\r
+ pushq %rax\r
+ movq %cr0, %rax\r
+ pushq %rax\r
+\r
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r
+ xorq %rax, %rax # set rax to 0\r
+ movzwq 56(%rbp), %rax\r
+# movq %ss, %rax\r
+ pushq %rax\r
+ movzwq 32(%rbp), %rax\r
+# movq %cs, %rax\r
+ pushq %rax\r
+ movq %ds, %rax\r
+ pushq %rax\r
+ movq %es, %rax\r
+ pushq %rax\r
+ movq %fs, %rax\r
+ pushq %rax\r
+ movq %gs, %rax\r
+ pushq %rax\r
+\r
+## UINT64 Rip;\r
+ pushq 24(%rbp)\r
+\r
+## UINT64 Gdtr[2], Idtr[2];\r
+ subq $16, %rsp\r
+ sidt (%rsp)\r
+ subq $16, %rsp\r
+ sgdt (%rsp)\r
+\r
+## UINT64 Ldtr, Tr;\r
+ xorq %rax, %rax\r
+ strw %ax\r
+ pushq %rax\r
+ sldtw %ax\r
+ pushq %rax\r
+\r
+## UINT64 RFlags;\r
+ pushq 40(%rbp)\r
+\r
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ movq %dr7, %rax\r
+ pushq %rax\r
+## clear Dr7 while executing debugger itself\r
+ xorq %rax, %rax\r
+#debug movq %rax, %dr7\r
+\r
+ movq %dr6, %rax\r
+ pushq %rax\r
+## insure all status bits in dr6 are clear...\r
+ xorq %rax, %rax\r
+ movq %rax, %dr6\r
+\r
+ movq %dr3, %rax\r
+ pushq %rax\r
+ movq %dr2, %rax\r
+ pushq %rax\r
+ movq %dr1, %rax\r
+ pushq %rax\r
+ movq %dr0, %rax\r
+ pushq %rax\r
+\r
+## FX_SAVE_STATE_X64 FxSaveState;\r
+ subq $512, %rsp\r
+ movq %rsp, %rdi\r
+ .byte 0x0f, 0xae, 0b00000111\r
+\r
+## Clear Direction Flag\r
+ cld\r
+\r
+## Prepare parameter and call\r
+# movq 8(%rbp), %rcx\r
+ movq %rsp, %rdx\r
+ movq %rcx, %r15 # save vector in r15\r
+ #\r
+ # Per X64 calling convention, allocate maximum parameter stack space\r
+ # and make sure RSP is 16-byte aligned\r
+ #\r
+ subq $(4 * 8), %rsp\r
+ call ASM_PFX(InterruptProcess)\r
+ addq $(4 * 8), %rsp\r
+\r
+## FX_SAVE_STATE_X64 FxSaveState;\r
+\r
+ movq %rsp, %rsi\r
+ .byte 0x0f, 0xae, 0b00001110\r
+ addq $512, %rsp\r
+\r
+## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ popq %rax\r
+ movq %rax, %dr0\r
+ popq %rax\r
+ movq %rax, %dr1\r
+ popq %rax\r
+ movq %rax, %dr2\r
+ popq %rax\r
+ movq %rax, %dr3\r
+## skip restore of dr6. We cleared dr6 during the context save.\r
+ addq $8, %rsp\r
+ popq %rax\r
+ movq %rax, %dr7\r
+\r
+## UINT64 RFlags;\r
+ popq 40(%rbp)\r
+\r
+## UINT64 Ldtr, Tr;\r
+## UINT64 Gdtr[2], Idtr[2];\r
+## Best not let anyone mess with these particular registers...\r
+ addq $48, %rsp\r
+\r
+## UINT64 Rip;\r
+ popq 24(%rbp)\r
+\r
+## UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+ popq %rax\r
+ # mov gs, rax ; not for gs\r
+ popq %rax\r
+ # mov fs, rax ; not for fs\r
+ # (X64 will not use fs and gs, so we do not restore it)\r
+ popq %rax\r
+ movw %rax, %es\r
+ popq %rax\r
+ movw %rax, %ds\r
+ popq 32(%rbp)\r
+ popq 56(%rbp)\r
+\r
+## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r
+ popq %rax\r
+ movq %rax, %cr0\r
+ addq $8, %rsp\r
+ popq %rax\r
+ movq %rax, %cr2\r
+ popq %rax\r
+ movq %rax, %cr3\r
+ popq %rax\r
+ movq %rax, %cr4\r
+\r
+## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r
+## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r
+ popq %rdi\r
+ popq %rsi\r
+ addq $8, %rsp\r
+ addq $8, %rsp\r
+ popq %rdx\r
+ popq %rcx\r
+ popq %rbx\r
+ popq %rax\r
+\r
+ popq %r8\r
+ movq %r8, %cr8\r
+\r
+ popq %r8\r
+ popq %r9\r
+ popq %r10\r
+ popq %r11\r
+ popq %r12\r
+ popq %r13\r
+ popq %r14\r
+ popq %r15\r
+\r
+ movq %rbp, %rsp\r
+ popq %rbp\r
+ addq $16, %rsp\r
+ iretq\r
--- /dev/null
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution. The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php.\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+; Module Name:\r
+;\r
+; AsmFuncs.asm\r
+;\r
+; Abstract:\r
+;\r
+; Debug interrupt handle functions.\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+#include "DebugException.h"\r
+\r
+\r
+externdef InterruptProcess:near\r
+\r
+data SEGMENT\r
+\r
+public Exception0Handle, TimerInterruptHandle, ExceptionStubHeaderSize\r
+\r
+ExceptionStubHeaderSize dw Exception1Handle - Exception0Handle ;\r
+CommonEntryAddr dq CommonEntry ;\r
+\r
+.code\r
+\r
+Exception0Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 0\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception1Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 1\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception2Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 2\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception3Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 3\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception4Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 4\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception5Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 5\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception6Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 6\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception7Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 7\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception8Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 8\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception9Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 9\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception10Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 10\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception11Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 11\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception12Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 12\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception13Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 13\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception14Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 14\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception15Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 15\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception16Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 16\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception17Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 17\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception18Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 18\r
+ jmp qword ptr [CommonEntryAddr]\r
+Exception19Handle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 19\r
+ jmp qword ptr [CommonEntryAddr]\r
+\r
+TimerInterruptHandle:\r
+ cli\r
+ push rcx\r
+ mov rcx, 32\r
+ jmp qword ptr [CommonEntryAddr]\r
+\r
+CommonEntry:\r
+ ; We need to determine if any extra data was pushed by the exception\r
+ cmp rcx, DEBUG_EXCEPT_DOUBLE_FAULT\r
+ je NoExtrPush\r
+ cmp rcx, DEBUG_EXCEPT_INVALID_TSS\r
+ je NoExtrPush\r
+ cmp rcx, DEBUG_EXCEPT_SEG_NOT_PRESENT\r
+ je NoExtrPush\r
+ cmp rcx, DEBUG_EXCEPT_STACK_FAULT\r
+ je NoExtrPush\r
+ cmp rcx, DEBUG_EXCEPT_GP_FAULT\r
+ je NoExtrPush\r
+ cmp rcx, DEBUG_EXCEPT_PAGE_FAULT\r
+ je NoExtrPush\r
+ cmp rcx, DEBUG_EXCEPT_ALIGNMENT_CHECK\r
+ je NoExtrPush\r
+\r
+ push [rsp]\r
+ mov qword ptr [rsp + 8], 0\r
+\r
+NoExtrPush:\r
+ push rbp\r
+ mov rbp, rsp\r
+\r
+ ; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15;\r
+ push r15\r
+ push r14\r
+ push r13\r
+ push r12\r
+ push r11\r
+ push r10\r
+ push r9\r
+ push r8\r
+\r
+ mov r8, cr8\r
+ push r8\r
+\r
+ ; store UINT64 Rdi, Rsi, Rbp, Rsp, Rdx, Rcx, Rbx, Rax;\r
+ push rax\r
+ push rbx\r
+ push qword ptr [rbp + 8] ; original rcx\r
+ push rdx\r
+ push qword ptr [rbp + 6 * 8] ; original rsp\r
+ push qword ptr [rbp] ; original rbp\r
+ push rsi\r
+ push rdi\r
+\r
+ ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ ;; insure FXSAVE/FXRSTOR is enabled in CR4...\r
+ ;; ... while we're at it, make sure DE is also enabled...\r
+ mov rax, cr4\r
+ or rax, 208h\r
+ mov cr4, rax\r
+ push rax\r
+ mov rax, cr3\r
+ push rax\r
+ mov rax, cr2\r
+ push rax\r
+ push 0 ; cr0 will not saved???\r
+ mov rax, cr0\r
+ push rax\r
+\r
+ xor rax, rax\r
+ mov rax, Ss\r
+ push rax\r
+ mov rax, Cs\r
+ push rax\r
+ mov rax, Ds\r
+ push rax\r
+ mov rax, Es\r
+ push rax\r
+ mov rax, Fs\r
+ push rax\r
+ mov rax, Gs\r
+ push rax\r
+\r
+ ;; EIP\r
+ mov rax, [rbp + 8 * 3] ; EIP\r
+ push rax\r
+\r
+ ;; UINT64 Gdtr[2], Idtr[2];\r
+ sub rsp, 16\r
+ sidt fword ptr [rsp]\r
+ sub rsp, 16\r
+ sgdt fword ptr [rsp]\r
+\r
+ ;; UINT64 Ldtr, Tr;\r
+ xor rax, rax\r
+ str ax\r
+ push rax\r
+ sldt ax\r
+ push rax\r
+\r
+ ;; EFlags\r
+ mov rax, [rbp + 8 * 5]\r
+ push rax\r
+\r
+ ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ mov rax, dr7\r
+ push rax\r
+\r
+ ;; clear Dr7 while executing debugger itself\r
+ xor rax, rax\r
+ mov dr7, rax\r
+\r
+ ;; Dr6\r
+ mov rax, dr6\r
+ push rax\r
+\r
+ ;; insure all status bits in dr6 are clear...\r
+ xor rax, rax\r
+ mov dr6, rax\r
+\r
+ mov rax, dr3\r
+ push rax\r
+ mov rax, dr2\r
+ push rax\r
+ mov rax, dr1\r
+ push rax\r
+ mov rax, dr0\r
+ push rax\r
+\r
+ sub rsp, 512\r
+ mov rdi, rsp\r
+ db 0fh, 0aeh, 00000111y ;fxsave [rdi]\r
+\r
+ ;; Clear Direction Flag\r
+ cld\r
+ \r
+ ; call the C interrupt process function\r
+ mov rdx, rsp ; Structure\r
+ mov r15, rcx ; save vector in r15\r
+ \r
+ sub rsp, 32\r
+ call InterruptProcess\r
+ add rsp, 32\r
+ \r
+ mov rsi, rsp\r
+ db 0fh, 0aeh, 00001110y ; fxrstor [rsi]\r
+ add rsp, 512\r
+\r
+ ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
+ pop rax\r
+ mov dr0, rax\r
+ pop rax\r
+ mov dr1, rax\r
+ pop rax\r
+ mov dr2, rax\r
+ pop rax\r
+ mov dr3, rax\r
+ ;; skip restore of dr6. We cleared dr6 during the context save.\r
+ add rsp, 8\r
+ pop rax\r
+ mov dr7, rax\r
+\r
+ ;; set EFlags\r
+ pop qword ptr [rbp + 8 * 5]\r
+\r
+ ;; UINT64 Ldtr, Tr;\r
+ ;; UINT64 Gdtr[2], Idtr[2];\r
+ ;; Best not let anyone mess with these particular registers...\r
+ add rsp, 24 * 2\r
+\r
+ ;; UINT64 Eip;\r
+ pop qword ptr [rbp + 8 * 3] ; set EIP in stack\r
+\r
+ ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r
+ ;; NOTE - modified segment registers could hang the debugger... We\r
+ ;; could attempt to insulate ourselves against this possibility,\r
+ ;; but that poses risks as well.\r
+ ;;\r
+ pop rax\r
+ pop rax\r
+ pop rax\r
+ mov es, rax\r
+ pop rax\r
+ mov ds, rax\r
+ pop qword ptr [rbp + 8 * 4] ; Set CS in stack\r
+ pop rax\r
+ mov ss, rax\r
+\r
+ ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ pop rax\r
+ mov cr0, rax\r
+ add rsp, 8 ; skip for Cr1\r
+ pop rax\r
+ mov cr2, rax\r
+ pop rax\r
+ mov cr3, rax\r
+ pop rax\r
+ mov cr4, rax\r
+\r
+ ;; restore general register\r
+ pop rdi\r
+ pop rsi\r
+ add rsp, 8 ; skip rbp\r
+ add rsp, 8 ; skip rsp\r
+ pop rdx\r
+ pop rcx\r
+ pop rbx\r
+ pop rax\r
+\r
+ pop r8\r
+ mov cr8, r8\r
+\r
+ ; store UINT64 r8, r9, r10, r11, r12, r13, r14, r15;\r
+ pop r8\r
+ pop r9\r
+ pop r10\r
+ pop r11\r
+ pop r12\r
+ pop r13\r
+ pop r14\r
+ pop r15\r
+\r
+ mov rsp, rbp\r
+ pop rbp\r
+ add rsp, 16 ; skip rcx and error code\r
+\r
+ iretq\r
+\r
+END\r
--- /dev/null
+/** @file\r
+ Exception defintions.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DEBUG_EXCEPTION_H_\r
+#define _DEBUG_EXCEPTION_H_\r
+\r
+#define DEBUG_EXCEPT_DIVIDE_ERROR 0\r
+#define DEBUG_EXCEPT_DEBUG 1\r
+#define DEBUG_EXCEPT_NMI 2\r
+#define DEBUG_EXCEPT_BREAKPOINT 3\r
+#define DEBUG_EXCEPT_OVERFLOW 4\r
+#define DEBUG_EXCEPT_BOUND 5\r
+#define DEBUG_EXCEPT_INVALID_OPCODE 6\r
+#define DEBUG_EXCEPT_DOUBLE_FAULT 8\r
+#define DEBUG_EXCEPT_INVALID_TSS 10\r
+#define DEBUG_EXCEPT_SEG_NOT_PRESENT 11\r
+#define DEBUG_EXCEPT_STACK_FAULT 12\r
+#define DEBUG_EXCEPT_GP_FAULT 13\r
+#define DEBUG_EXCEPT_PAGE_FAULT 14\r
+#define DEBUG_EXCEPT_FP_ERROR 16\r
+#define DEBUG_EXCEPT_ALIGNMENT_CHECK 17\r
+#define DEBUG_EXCEPT_MACHINE_CHECK 18\r
+#define DEBUG_EXCEPT_SIMD 19\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ Debug Agent library implementition for Dxe Core and Dxr modules.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "DxeDebugAgentLib.h"\r
+\r
+DEBUG_AGENT_MAILBOX mMailbox;\r
+\r
+DEBUG_AGENT_MAILBOX *mMailboxPointer;\r
+\r
+IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];\r
+\r
+BOOLEAN mConfigurationTableNeeded = FALSE;\r
+\r
+CONST BOOLEAN MultiProcessorDebugSupport = TRUE;\r
+\r
+/**\r
+ Constructor allocates the NVS memory to store Mailbox and install configuration table\r
+ in system table to store its pointer.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval RETURN_SUCCESS Allocate the global memory space to store guid and function tables.\r
+ @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+DxeDebugAgentLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+\r
+ if (!mConfigurationTableNeeded) {\r
+ return RETURN_SUCCESS;\r
+ }\r
+\r
+ Address = 0;\r
+ Status = gBS->AllocatePages (\r
+ AllocateAnyPages,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX)),\r
+ &Address\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (\r
+ (UINT8 *) (UINTN) Address,\r
+ (UINT8 *) (UINTN) mMailboxPointer,\r
+ sizeof (DEBUG_AGENT_MAILBOX)\r
+ );\r
+\r
+ mMailboxPointer = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;\r
+\r
+ return gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer);\r
+}\r
+\r
+/**\r
+ Get the pointer to Mailbox from the GUIDed HOB.\r
+\r
+ @param[in] HobStart The starting HOB pointer to search from.\r
+\r
+ @return Pointer to Mailbox.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+GetMailboxFromHob (\r
+ IN VOID *HobStart\r
+ )\r
+{\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+\r
+ GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);\r
+ if (GuidHob == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ return (DEBUG_AGENT_MAILBOX *) (GET_GUID_HOB_DATA(GuidHob));\r
+}\r
+\r
+/**\r
+ Get Debug Agent Mailbox pointer.\r
+\r
+ @return Mailbox pointer.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+GetMailboxPointer (\r
+ VOID\r
+ )\r
+{\r
+ return mMailboxPointer;\r
+}\r
+\r
+/**\r
+ Get debug port handle.\r
+\r
+ @return Debug port handle.\r
+\r
+**/\r
+DEBUG_PORT_HANDLE\r
+GetDebugPortHandle (\r
+ VOID\r
+ )\r
+{\r
+ return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);\r
+}\r
+\r
+ \r
+/**\r
+ Initialize debug agent.\r
+\r
+ This function is used to set up debug enviroment for DXE phase.\r
+\r
+ If this function is called by DXE Core, Context must be the pointer\r
+ to HOB list which will be used to get GUIDed HOB. It will enable\r
+ interrupt to support break-in feature.\r
+ If this function is called by DXE module, Context must be NULL. It\r
+ will enable interrupt to support break-in feature.\r
+\r
+ @param[in] InitFlag Init flag is used to decide initialize process.\r
+ @param[in] Context Context needed according to InitFlag.\r
+ @param[in] Function Continue function called by debug agent library; it was\r
+ optional.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeDebugAgent (\r
+ IN UINT32 InitFlag,\r
+ IN VOID *Context, OPTIONAL\r
+ IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
+ )\r
+{\r
+ DEBUG_AGENT_MAILBOX *Mailbox;\r
+ IA32_DESCRIPTOR Idtr;\r
+ UINT16 IdtEntryCount;\r
+ BOOLEAN InterruptStatus;\r
+\r
+ if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE &&\r
+ InitFlag != DEBUG_AGENT_INIT_S3 &&\r
+ InitFlag != DEBUG_AGENT_INIT_DXE_AP) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Save and disable original interrupt status\r
+ //\r
+ InterruptStatus = SaveAndDisableInterrupts ();\r
+\r
+ if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {\r
+ //\r
+ // Try to get Mailbox from GUIDed HOB.\r
+ //\r
+ mConfigurationTableNeeded = TRUE;\r
+ Mailbox = GetMailboxFromHob (Context);\r
+\r
+ } else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {\r
+\r
+ EnableInterrupts ();\r
+\r
+ return;\r
+\r
+ } else {\r
+ //\r
+ // If it is in S3 path, needn't to install configuration table.\r
+ //\r
+ Mailbox = NULL;\r
+ }\r
+\r
+ if (Mailbox != NULL) {\r
+ //\r
+ // If Mailbox exists, copy it into one global variable.\r
+ //\r
+ CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
+ mMailbox.DebugPortHandle = 0;\r
+ } else {\r
+ //\r
+ // If Mailbox not exists, used the local Mailbox.\r
+ //\r
+ ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
+ }\r
+\r
+ mMailboxPointer = &mMailbox;\r
+\r
+ //\r
+ // Get original IDT address and size.\r
+ //\r
+ AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
+ IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+ if (IdtEntryCount < 33) {\r
+ Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);\r
+ Idtr.Base = (UINTN) &mIdtEntryTable;\r
+ AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
+ }\r
+\r
+ //\r
+ // Initialize the IDT table entries to support source level debug.\r
+ //\r
+ InitializeDebugIdt ();\r
+\r
+ //\r
+ // Initialize debug communication port\r
+ //\r
+ mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize (NULL, NULL);\r
+\r
+ InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);\r
+ InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
+ \r
+ if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {\r
+ //\r
+ // Initialize Debug Timer hardware and enable interrupt.\r
+ //\r
+ InitializeDebugTimer ();\r
+ EnableInterrupts ();\r
+\r
+ return;\r
+ } else {\r
+ //\r
+ // Disable Debug Timer interrupt in S3 path.\r
+ //\r
+ SaveAndSetDebugTimerInterrupt (FALSE);\r
+\r
+ //\r
+ // Restore interrupt state.\r
+ //\r
+ SetInterruptState (InterruptStatus);\r
+ }\r
+\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Header file for Dxe Core Debug Agent Library instance.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DXE_CORE_DEBUG_AGENT_LIB_H_\r
+#define _DXE_CORE_DEBUG_AGENT_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include "DebugAgent.h"\r
+\r
+#endif\r
--- /dev/null
+## @file\r
+# Debug Agent library instance for Dxe Core and Dxe modules.\r
+#\r
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DxeDebugAgentLib\r
+ FILE_GUID = BA6BAD25-B814-4747-B0B0-0FBB61D40B90\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 0.7\r
+ LIBRARY_CLASS = DebugAgentLib|DXE_CORE DXE_DRIVER\r
+\r
+ CONSTRUCTOR = DxeDebugAgentLibConstructor\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+ DxeDebugAgent/DxeDebugAgentLib.c\r
+ DxeDebugAgent/DxeDebugAgentLib.h\r
+ DebugAgentCommon/DebugAgent.c\r
+ DebugAgentCommon/DebugAgent.h\r
+ DebugAgentCommon/DebugTimer.c\r
+ DebugAgentCommon/DebugTimer.h\r
+ DebugAgentCommon/DebugMp.c\r
+ DebugAgentCommon/DebugMp.h\r
+\r
+[Sources.Ia32]\r
+ DebugAgentCommon/Ia32/AsmFuncs.S | GCC\r
+ DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT\r
+ DebugAgentCommon/Ia32/ArchDebugSupport.h\r
+ DebugAgentCommon/Ia32/ArchDebugSupport.c\r
+ DebugAgentCommon/Ia32/ArchReadGroupRegister.c\r
+ DebugAgentCommon/Ia32/ArchRegisters.h\r
+ DebugAgentCommon/Ia32/DebugException.h\r
+\r
+[Sources.X64]\r
+ DebugAgentCommon/X64/AsmFuncs.S | GCC\r
+ DebugAgentCommon/X64/AsmFuncs.asm | MSFT\r
+ DebugAgentCommon/X64/ArchDebugSupport.h\r
+ DebugAgentCommon/X64/ArchDebugSupport.c\r
+ DebugAgentCommon/X64/ArchReadGroupRegister.c\r
+ DebugAgentCommon/X64/ArchRegisters.h\r
+ DebugAgentCommon/X64/DebugException.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ UefiCpuPkg/UefiCpuPkg.dec\r
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ ResetSystemLib\r
+ IoLib\r
+ HobLib\r
+ DebugCommunicationLib\r
+ UefiBootServicesTableLib\r
+ UefiLib\r
+ PcdLib\r
+ SynchronizationLib\r
+ MemoryAllocationLib\r
+ LocalApicLib\r
+\r
+[Guids]\r
+ gEfiDebugAgentGuid ## PRODUCES ## Configuration Table\r
+ gEfiDebugAgentGuid ## CONSUMES ## HOB\r
+\r
+[Pcd]\r
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES\r
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES\r
+\r
--- /dev/null
+/** @file\r
+ SEC Core Debug Agent Library instance implementition.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SecPeiDebugAgentLib.h"\r
+\r
+CONST BOOLEAN MultiProcessorDebugSupport = FALSE;\r
+\r
+/**\r
+ Get pointer to Mailbox from IDT entry before memory is ready.\r
+\r
+**/\r
+VOID *\r
+GetMailboxPointerInIdtEntry (\r
+ VOID\r
+ )\r
+{\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+ UINTN Mailbox;\r
+\r
+ AsmReadIdtr (&IdtDescriptor);\r
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+ Mailbox = IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + (IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16);\r
+ return (VOID *) Mailbox;\r
+}\r
+\r
+/**\r
+ Set the pointer of Mailbox into IDT entry before memory is ready.\r
+\r
+ @param[in] Mailbox The pointer of Mailbox.\r
+\r
+**/\r
+VOID\r
+SetMailboxPointerInIdtEntry (\r
+ IN VOID *Mailbox\r
+ )\r
+{\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtEntry;\r
+ IA32_DESCRIPTOR IdtDescriptor;\r
+\r
+ AsmReadIdtr (&IdtDescriptor);\r
+ IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+\r
+ IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)Mailbox;\r
+ IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)Mailbox >> 16);\r
+}\r
+\r
+/**\r
+ Get the pointer to Mailbox from IDT entry and build the Mailbox into GUIDed Hob\r
+ after memory is ready.\r
+\r
+ @return Pointer to Mailbox.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+BuildMailboxHob (\r
+ VOID\r
+ )\r
+{\r
+ DEBUG_AGENT_MAILBOX *Mailbox;\r
+\r
+ Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();\r
+\r
+ return BuildGuidDataHob (\r
+ &gEfiDebugAgentGuid,\r
+ Mailbox,\r
+ sizeof (DEBUG_AGENT_MAILBOX)\r
+ );\r
+}\r
+\r
+/**\r
+ Get Debug Agent Mailbox pointer.\r
+\r
+ @return Mailbox pointer.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+GetMailboxPointer (\r
+ VOID\r
+ )\r
+{\r
+ return (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();\r
+}\r
+\r
+/**\r
+ Get debug port handle.\r
+\r
+ @return Debug port handle.\r
+\r
+**/\r
+DEBUG_PORT_HANDLE\r
+GetDebugPortHandle (\r
+ VOID\r
+ )\r
+{\r
+ DEBUG_AGENT_MAILBOX *DebugAgentMailbox;\r
+ \r
+ DebugAgentMailbox = (DEBUG_AGENT_MAILBOX *)GetMailboxPointerInIdtEntry ();\r
+\r
+ return (DEBUG_PORT_HANDLE) (UINTN)(DebugAgentMailbox->DebugPortHandle);\r
+}\r
+\r
+/**\r
+ Trigger one software interrupt to debug agent to handle it.\r
+\r
+ @param Signature Software interrupt signature.\r
+\r
+**/\r
+VOID\r
+TriggerSoftInterrupt (\r
+ UINT32 Signature\r
+ )\r
+{\r
+ UINTN Dr0;\r
+ UINTN Dr1;\r
+\r
+ //\r
+ // Save Debug Register State\r
+ //\r
+ Dr0 = AsmReadDr0 ();\r
+ Dr1 = AsmReadDr1 ();\r
+\r
+ //\r
+ // DR0 = Signature\r
+ //\r
+ AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);\r
+ AsmWriteDr1 (Signature);\r
+\r
+ //\r
+ // Do INT3 to communicate with HOST side\r
+ //\r
+ CpuBreakpoint ();\r
+\r
+ //\r
+ // Restore Debug Register State only when Host didn't change it inside exception handler.\r
+ // Dr registers can only be changed by setting the HW breakpoint.\r
+ //\r
+ AsmWriteDr0 (Dr0);\r
+ AsmWriteDr1 (Dr1);\r
+\r
+}\r
+\r
+/**\r
+ Initialize debug agent.\r
+\r
+ This function is used to set up debug environment for SEC and PEI phase.\r
+\r
+ If InitFlag is DEBUG_AGENT_INIT_PREMEM_SEC, it will overirde IDT table entries\r
+ and initialize debug port. It will enable interrupt to support break-in feature.\r
+ It will set up debug agent Mailbox in cache-as-ramfrom. It will be called before\r
+ physical memory is ready.\r
+ If InitFlag is DEBUG_AGENT_INIT_POSTMEM_SEC, debug agent will build one GUIDed\r
+ HOB to copy debug agent Mailbox. It will be called after physical memory is ready.\r
+\r
+ This function is used to set up debug environment to support source level debugging.\r
+ If certain Debug Agent Library instance has to save some private data in the stack,\r
+ this function must work on the mode that doesn't return to the caller, then\r
+ the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one\r
+ function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is\r
+ responsible to invoke the passing-in function at the end of InitializeDebugAgent().\r
+\r
+ If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by\r
+ passing in the Context to be its parameter.\r
+\r
+ If Function() is NULL, Debug Agent Library instance will return after setup debug\r
+ environment.\r
+\r
+ @param[in] InitFlag Init flag is used to decide the initialize process.\r
+ @param[in] Context Context needed according to InitFlag; it was optional.\r
+ @param[in] Function Continue function called by debug agent library; it was\r
+ optional.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeDebugAgent (\r
+ IN UINT32 InitFlag,\r
+ IN VOID *Context, OPTIONAL\r
+ IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
+ )\r
+{\r
+ DEBUG_AGENT_MAILBOX *Mailbox;\r
+ DEBUG_AGENT_MAILBOX MailboxInStack;\r
+ DEBUG_AGENT_PHASE2_CONTEXT Phase2Context;\r
+ DEBUG_AGENT_CONTEXT_POSTMEM_SEC *DebugAgentContext;\r
+\r
+ if (InitFlag != DEBUG_AGENT_INIT_PREMEM_SEC &&\r
+ InitFlag != DEBUG_AGENT_INIT_POSTMEM_SEC) {\r
+ return;\r
+ }\r
+\r
+ DisableInterrupts ();\r
+\r
+ if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {\r
+\r
+ //\r
+ // Memory has been ready\r
+ //\r
+ if (IsHostConnected()) {\r
+ //\r
+ // Trigger one software interrupt to inform HOST\r
+ //\r
+ TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
+ }\r
+\r
+ DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *) Context;\r
+\r
+ Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();\r
+ Mailbox->DebugPortHandle = Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset;\r
+\r
+ Mailbox = BuildMailboxHob ();\r
+ Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->HeapMigrateOffset);\r
+\r
+ SetMailboxPointerInIdtEntry ((VOID *) Mailbox);\r
+\r
+ EnableInterrupts ();\r
+\r
+ if (Function != NULL) {\r
+ Function (Context);\r
+ }\r
+\r
+ return;\r
+\r
+ } else {\r
+\r
+ InitializeDebugIdt ();\r
+\r
+ Mailbox = &MailboxInStack;\r
+ ZeroMem ((VOID *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
+\r
+ //\r
+ // Get and save debug port handle and set the length of memory block.\r
+ //\r
+ SetMailboxPointerInIdtEntry ((VOID *) Mailbox);\r
+\r
+ InitializeDebugTimer ();\r
+\r
+ Phase2Context.Context = Context;\r
+ Phase2Context.Function = Function;\r
+ DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);\r
+\r
+ return;\r
+ }\r
+}\r
+\r
+/**\r
+ Caller provided function to be invoked at the end of DebugPortInitialize().\r
+\r
+ Refer to the descrption for DebugPortInitialize() for more details.\r
+\r
+ @param[in] Context The first input argument of DebugPortInitialize().\r
+ @param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeDebugAgentPhase2 (\r
+ IN VOID *Context,\r
+ IN DEBUG_PORT_HANDLE DebugPortHandle\r
+ )\r
+{\r
+ DEBUG_AGENT_PHASE2_CONTEXT *Phase2Context;\r
+ DEBUG_AGENT_MAILBOX *Mailbox;\r
+ EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
+\r
+ Mailbox = GetMailboxPointerInIdtEntry ();\r
+ Mailbox->DebugPortHandle = (UINT64) (UINTN)DebugPortHandle;\r
+\r
+ //\r
+ // Trigger one software interrupt to inform HOST\r
+ //\r
+ TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);\r
+\r
+ //\r
+ // If Temporary RAM region is below 128 MB, then send message to \r
+ // host to disable low memory filtering.\r
+ //\r
+ Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context;\r
+ SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context;\r
+ if ((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB) {\r
+ TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
+ }\r
+\r
+ //\r
+ // Enable CPU interrupts so debug timer interrupts can be delivered\r
+ //\r
+ EnableInterrupts ();\r
+\r
+ //\r
+ // Call continuation function is it is not NULL.\r
+ //\r
+ if (Phase2Context->Function != NULL) {\r
+ Phase2Context->Function (Phase2Context->Context);\r
+ }\r
+}\r
--- /dev/null
+/** @file\r
+ Header file for Sec Core Debug Agent Library instance.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _SEC_CORE_DEBUG_AGENT_LIB_H_\r
+#define _SEC_CORE_DEBUG_AGENT_LIB_H_\r
+\r
+#include <PiPei.h>\r
+\r
+#include "DebugAgent.h"\r
+\r
+typedef struct {\r
+ VOID *Context;\r
+ DEBUG_AGENT_CONTINUE Function;\r
+} DEBUG_AGENT_PHASE2_CONTEXT;\r
+\r
+#endif\r
+\r
--- /dev/null
+## @file\r
+# Debug Agent library instance for SEC Core and PEI modules.\r
+#\r
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = SecPeiDebugAgentLib\r
+ FILE_GUID = 508B7D59-CD4E-4a6b-A45B-6D3B2D90111E\r
+ MODULE_TYPE = PEIM\r
+ VERSION_STRING = 0.7\r
+ LIBRARY_CLASS = DebugAgentLib|SEC PEIM\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+ SecPeiDebugAgent/SecPeiDebugAgentLib.c\r
+ SecPeiDebugAgent/SecPeiDebugAgentLib.h\r
+ DebugAgentCommon/DebugAgent.c\r
+ DebugAgentCommon/DebugAgent.h\r
+ DebugAgentCommon/DebugTimer.c\r
+ DebugAgentCommon/DebugTimer.h\r
+ DebugAgentCommon/DebugMp.c\r
+ DebugAgentCommon/DebugMp.h\r
+\r
+[Sources.Ia32]\r
+ DebugAgentCommon/Ia32/AsmFuncs.S | GCC\r
+ DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT\r
+ DebugAgentCommon/Ia32/ArchDebugSupport.h\r
+ DebugAgentCommon/Ia32/ArchDebugSupport.c\r
+ DebugAgentCommon/Ia32/ArchReadGroupRegister.c\r
+ DebugAgentCommon/Ia32/ArchRegisters.h\r
+ DebugAgentCommon/Ia32/DebugException.h\r
+\r
+[Sources.X64]\r
+ DebugAgentCommon/X64/AsmFuncs.S | GCC\r
+ DebugAgentCommon/X64/AsmFuncs.asm | MSFT\r
+ DebugAgentCommon/X64/ArchDebugSupport.h\r
+ DebugAgentCommon/X64/ArchDebugSupport.c\r
+ DebugAgentCommon/X64/ArchReadGroupRegister.c\r
+ DebugAgentCommon/X64/ArchRegisters.h\r
+ DebugAgentCommon/X64/DebugException.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ UefiCpuPkg/UefiCpuPkg.dec\r
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ ResetSystemLib\r
+ IoLib\r
+ HobLib\r
+ PcdLib\r
+ DebugCommunicationLib\r
+ SynchronizationLib\r
+ LocalApicLib\r
+\r
+[Guids]\r
+ gEfiDebugAgentGuid ## PRODUCES ## HOB\r
+\r
+[Pcd]\r
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES\r
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES\r
+\r
--- /dev/null
+/** @file\r
+ Debug Agent library implementition.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SmmDebugAgentLib.h"\r
+\r
+DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED DEBUG_AGENT_MAILBOX mLocalMailbox;\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSavedDebugRegisters[6];\r
+\r
+CONST BOOLEAN MultiProcessorDebugSupport = FALSE;\r
+\r
+\r
+/**\r
+ Get Debug Agent Mailbox pointer.\r
+\r
+ @return Mailbox pointer.\r
+\r
+**/\r
+DEBUG_AGENT_MAILBOX *\r
+GetMailboxPointer (\r
+ VOID\r
+ )\r
+{\r
+ return mMailboxPointer;\r
+}\r
+\r
+/**\r
+ Get debug port handle.\r
+\r
+ @return Debug port handle.\r
+\r
+**/\r
+DEBUG_PORT_HANDLE\r
+GetDebugPortHandle (\r
+ VOID\r
+ )\r
+{\r
+ return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);\r
+}\r
+\r
+/**\r
+ Store debug register when SMI exit.\r
+\r
+**/\r
+VOID\r
+SaveDebugRegister (\r
+ VOID\r
+ )\r
+{\r
+ mSavedDebugRegisters[0] = AsmReadDr0 ();\r
+ mSavedDebugRegisters[1] = AsmReadDr1 ();\r
+ mSavedDebugRegisters[2] = AsmReadDr2 ();\r
+ mSavedDebugRegisters[3] = AsmReadDr3 ();\r
+ mSavedDebugRegisters[4] = AsmReadDr6 ();\r
+ mSavedDebugRegisters[5] = AsmReadDr7 ();\r
+}\r
+\r
+/**\r
+ Restore debug register when SMI exit.\r
+\r
+**/\r
+VOID\r
+RestoreDebugRegister (\r
+ VOID\r
+ )\r
+{\r
+ AsmWriteDr7 (0);\r
+ AsmWriteDr0 (mSavedDebugRegisters[0]);\r
+ AsmWriteDr1 (mSavedDebugRegisters[1]);\r
+ AsmWriteDr2 (mSavedDebugRegisters[2]);\r
+ AsmWriteDr3 (mSavedDebugRegisters[3]);\r
+ AsmWriteDr6 (mSavedDebugRegisters[4]);\r
+ AsmWriteDr7 (mSavedDebugRegisters[5]);\r
+}\r
+\r
+/**\r
+ Initialize debug agent.\r
+\r
+ This function is used to set up debug enviroment for source level debug\r
+ in SMM code.\r
+\r
+ If InitFlag is DEBUG_AGENT_INIT_SMM, it will overirde IDT table entries\r
+ and initialize debug port. It will get debug agent Mailbox from GUIDed HOB,\r
+ it it exists, debug agent wiil copied it into the local Mailbox in SMM space.\r
+ it will overirde IDT table entries and initialize debug port. Context will be\r
+ NULL.\r
+ If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug\r
+ Registers and get local Mailbox in SMM space. Context will be NULL.\r
+ If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug\r
+ Registers. Context will be NULL.\r
+\r
+ @param[in] InitFlag Init flag is used to decide initialize process.\r
+ @param[in] Context Context needed according to InitFlag.\r
+ @param[in] Function Continue function called by debug agent library; it was\r
+ optional.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeDebugAgent (\r
+ IN UINT32 InitFlag,\r
+ IN VOID *Context, OPTIONAL\r
+ IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT64 DebugPortHandle;\r
+\r
+ switch (InitFlag) {\r
+ case DEBUG_AGENT_INIT_SMM:\r
+ Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &mMailboxPointer);\r
+ if (EFI_ERROR (Status) || mMailboxPointer == NULL) {\r
+ ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
+ mMailboxPointer = &mLocalMailbox;\r
+ }\r
+\r
+ break;\r
+\r
+ case DEBUG_AGENT_INIT_ENTER_SMI:\r
+ SaveDebugRegister ();\r
+ InitializeDebugIdt ();\r
+\r
+ if (mMailboxPointer != NULL) {\r
+ //\r
+ // Initialize debug communication port\r
+ //\r
+ DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)mMailboxPointer->DebugPortHandle, NULL);\r
+ mMailboxPointer->DebugPortHandle = DebugPortHandle;\r
+\r
+ if (mMailboxPointer->DebugFlag.Bits.BreakOnNextSmi == 1) {\r
+ //\r
+ // If SMM entry break is set, SMM code will be break at here.\r
+ //\r
+ CpuBreakpoint ();\r
+ }\r
+ }\r
+ break;\r
+\r
+ case DEBUG_AGENT_INIT_EXIT_SMI:\r
+ RestoreDebugRegister ();\r
+ break;\r
+ }\r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Header file for Smm Debug Agent Library instance.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _SMM_DEBUG_AGENT_LIB_H_\r
+#define _SMM_DEBUG_AGENT_LIB_H_\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Library/UefiLib.h>\r
+\r
+#include "DebugAgent.h"\r
+\r
+#endif\r
--- /dev/null
+## @file\r
+# Debug Agent library instance for SMM modules.\r
+#\r
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = SecDebugAgentLib\r
+ FILE_GUID = CB07D74C-598F-4268-A5D1-644FB4A481E8\r
+ MODULE_TYPE = DXE_SMM_DRIVER\r
+ VERSION_STRING = 0.7\r
+ LIBRARY_CLASS = DebugAgentLib|DXE_SMM_DRIVER\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+ SmmDebugAgent/SmmDebugAgentLib.c\r
+ SmmDebugAgent/SmmDebugAgentLib.h\r
+ DebugAgentCommon/DebugAgent.c\r
+ DebugAgentCommon/DebugAgent.h\r
+ DebugAgentCommon/DebugTimer.c\r
+ DebugAgentCommon/DebugTimer.h\r
+ DebugAgentCommon/DebugMp.c\r
+ DebugAgentCommon/DebugMp.h\r
+\r
+[Sources.Ia32]\r
+ DebugAgentCommon/Ia32/AsmFuncs.S | GCC\r
+ DebugAgentCommon/Ia32/AsmFuncs.asm | MSFT\r
+ DebugAgentCommon/Ia32/ArchDebugSupport.h\r
+ DebugAgentCommon/Ia32/ArchDebugSupport.c\r
+ DebugAgentCommon/Ia32/ArchReadGroupRegister.c\r
+ DebugAgentCommon/Ia32/ArchRegisters.h\r
+ DebugAgentCommon/Ia32/DebugException.h\r
+\r
+[Sources.X64]\r
+ DebugAgentCommon/X64/AsmFuncs.S | GCC\r
+ DebugAgentCommon/X64/AsmFuncs.asm | MSFT\r
+ DebugAgentCommon/X64/ArchDebugSupport.h\r
+ DebugAgentCommon/X64/ArchDebugSupport.c\r
+ DebugAgentCommon/X64/ArchReadGroupRegister.c\r
+ DebugAgentCommon/X64/ArchRegisters.h\r
+ DebugAgentCommon/X64/DebugException.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ UefiCpuPkg/UefiCpuPkg.dec\r
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ BaseMemoryLib\r
+ ResetSystemLib\r
+ IoLib\r
+ DebugCommunicationLib\r
+ UefiLib\r
+ PcdLib\r
+ SynchronizationLib\r
+ LocalApicLib\r
+\r
+[Guids]\r
+ gEfiDebugAgentGuid ## CONSUMES ## Configuration Table\r
+\r
+[Pcd]\r
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock ## CONSUMES\r
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdExceptionsIgnoredByDebugger ## CONSUMES\r
+\r
--- /dev/null
+/** @file\r
+ Debug Port Library implementation based on serial port.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+\r
+#include <Library/DebugCommunicationLib.h>\r
+#include <Library/SerialPortLib.h>\r
+#include <Library/TimerLib.h>\r
+\r
+/**\r
+ Initialize the debug port.\r
+\r
+ This function will initialize debug port to get it ready for data transmition. If\r
+ certain Debug Communication Library instance has to save some private data in the\r
+ stack, this function must work on the mode that doesn't return to the caller, then\r
+ the caller needs to wrap up all rest of logic after DebugPortInitialize() into one\r
+ function and pass it into DebugPortInitialize(). DebugPortInitialize() is\r
+ responsible to invoke the passing-in funciton at the end of DebugPortInitialize().\r
+\r
+ If the paramter Function is not NULL, Debug Communication Libary instance will\r
+ invoke it by passing in the Context to be the first parameter. Debug Communication\r
+ Library instance could create one debug port handle to be the second parameter\r
+ passing into the Function. Debug Communication Library instance also could pass\r
+ NULL to be the second parameter if it doesn't create the debug port handle.\r
+\r
+ If the parameter Function is NULL, and Context is not NULL. At this time, Context\r
+ is the debug port handle created by the previous Debug Communication Library\r
+ instance.\r
+ a) If the instance can understand and continue use the private data of the previous\r
+ instance, it could return the same handle as passed in (as Context parameter).\r
+ b) If the instance does not understand, or does not want to continue use the\r
+ private data of the previous instance, it could ignore the input Context parameter\r
+ and create the new hanlde to be returned.\r
+\r
+ If Function() is NULL and Context is NULL, Debug Communication Library could create a\r
+ new handle and return it. NULL is also a valid handle to be returned.\r
+\r
+ @param[in] Context Context needed by callback function; it was optional.\r
+ @param[in] Function Continue function called by Debug Communication library;\r
+ it was optional.\r
+\r
+ @return The debug port handle created by Debug Communication Library if Function\r
+ is not NULL.\r
+\r
+**/\r
+DEBUG_PORT_HANDLE\r
+EFIAPI\r
+DebugPortInitialize (\r
+ IN VOID *Context,\r
+ IN DEBUG_PORT_CONTINUE Function\r
+ )\r
+{\r
+ SerialPortInitialize ();\r
+\r
+ if (Function != NULL) {\r
+ Function (Context, NULL);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Read data from debug device and save the datas in buffer.\r
+\r
+ Reads NumberOfBytes data bytes from a debug device into the buffer\r
+ specified by Buffer. The number of bytes actually read is returned.\r
+ If the return value is less than NumberOfBytes, then the rest operation failed.\r
+ If NumberOfBytes is zero, then return 0.\r
+\r
+ @param Handle Debug port handle.\r
+ @param Buffer Pointer to the data buffer to store the data read from the debug device.\r
+ @param NumberOfBytes Number of bytes which will be read.\r
+ @param Timeout Timeout value for reading from debug device. It unit is Microsecond.\r
+\r
+ @retval 0 Read data failed, no data is to be read.\r
+ @retval >0 Actual number of bytes read from debug device.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+DebugPortReadBuffer (\r
+ IN DEBUG_PORT_HANDLE Handle,\r
+ IN UINT8 *Buffer,\r
+ IN UINTN NumberOfBytes,\r
+ IN UINTN Timeout\r
+ )\r
+{\r
+ UINTN Index;\r
+ INTN Elapsed;\r
+\r
+ for (Index = 0; Index < NumberOfBytes; Index ++) {\r
+ Elapsed = (INTN) Timeout;\r
+ while (TRUE) {\r
+ if (SerialPortPoll () || Timeout == 0) {\r
+ SerialPortRead (Buffer + Index, 1);\r
+ break;\r
+ }\r
+ MicroSecondDelay (1000);\r
+ Elapsed -= 1000;\r
+ if (Elapsed < 0) {\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ return NumberOfBytes;\r
+}\r
+\r
+/**\r
+ Write data from buffer to debug device.\r
+\r
+ Writes NumberOfBytes data bytes from Buffer to the debug device.\r
+ The number of bytes actually written to the debug device is returned.\r
+ If the return value is less than NumberOfBytes, then the write operation failed.\r
+ If NumberOfBytes is zero, then return 0.\r
+\r
+ @param Handle Debug port handle.\r
+ @param Buffer Pointer to the data buffer to be written.\r
+ @param NumberOfBytes Number of bytes to written to the debug device.\r
+\r
+ @retval 0 NumberOfBytes is 0.\r
+ @retval >0 The number of bytes written to the debug device.\r
+ If this value is less than NumberOfBytes, then the read operation failed.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+DebugPortWriteBuffer (\r
+ IN DEBUG_PORT_HANDLE Handle,\r
+ IN UINT8 *Buffer,\r
+ IN UINTN NumberOfBytes\r
+ )\r
+{\r
+ return SerialPortWrite (Buffer, NumberOfBytes);\r
+}\r
+\r
+/**\r
+ Polls a debug device to see if there is any data waiting to be read.\r
+\r
+ Polls a debug device to see if there is any data waiting to be read.\r
+ If there is data waiting to be read from the debug device, then TRUE is returned.\r
+ If there is no data waiting to be read from the debug device, then FALSE is returned.\r
+\r
+ @param Handle Debug port handle.\r
+\r
+ @retval TRUE Data is waiting to be read from the debug device.\r
+ @retval FALSE There is no data waiting to be read from the serial device.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+DebugPortPollBuffer (\r
+ IN DEBUG_PORT_HANDLE Handle\r
+ )\r
+{\r
+ return SerialPortPoll ();\r
+}\r
+\r
--- /dev/null
+## @file\r
+# Debug Communication Library instance based on serila port.\r
+#\r
+# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php.\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DebugCommunicationLibSerialPort\r
+ FILE_GUID = 8CC435C5-6330-4269-B0C3-E3BD05C86FB8\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 0.7\r
+ LIBRARY_CLASS = DebugCommunicationLib\r
+\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64\r
+#\r
+\r
+[Sources.common]\r
+ DebugCommunicationLibSerialPort.c\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec\r
+\r
+[LibraryClasses]\r
+ SerialPortLib\r
+ TimerLib\r
+ \r
--- /dev/null
+/** @file\r
+ Debug Port Library implementation based on usb debug port.\r
+\r
+ Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php.\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/Usb.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/TimerLib.h>\r
+#include <Library/DebugCommunicationLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+\r
+#define SETUP_PID 0x2D\r
+#define INPUT_PID 0x69\r
+#define OUTPUT_PID 0xE1\r
+#define ERROR_PID 0x55\r
+#define DATA0_PID 0xC3\r
+#define DATA1_PID 0x4B\r
+#define DATA2_PID 0x87\r
+#define MDATA_PID 0x0F\r
+#define ACK_PID 0xD2\r
+#define NAK_PID 0x5A\r
+#define STALL_PID 0x1E\r
+#define NYET_PID 0x96\r
+\r
+#define PCI_CAPABILITY_ID_DEBUG_PORT 0x0A\r
+#define USB_DEBUG_PORT_MAX_PACKET_SIZE 0x08\r
+\r
+#define USB_DEBUG_PORT_IN_USE BIT10\r
+#define USB_DEBUG_PORT_ENABLE BIT28\r
+#define USB_DEBUG_PORT_OWNER BIT30\r
+\r
+#define USB_PORT_LINE_STATUS_LS 0x400\r
+#define USB_PORT_LINE_STATUS_MASK 0xC00\r
+\r
+//\r
+// Usb debug device descriptor, which is defined at\r
+// USB2 Debug Device Specification.\r
+//\r
+typedef struct _USB_DEBUG_PORT_DESCRIPTOR {\r
+ UINT8 Length;\r
+ UINT8 DescriptorType;\r
+ UINT8 DebugInEndpoint;\r
+ UINT8 DebugOutEndpoint;\r
+}USB_DEBUG_PORT_DESCRIPTOR;\r
+\r
+USB_DEVICE_REQUEST mGetDebugDescriptor = {\r
+ 0x80,\r
+ USB_REQ_GET_DESCRIPTOR,\r
+ (UINT16)(0x0A << 8),\r
+ 0x0000,\r
+ sizeof(USB_DEBUG_PORT_DESCRIPTOR)\r
+ };\r
+\r
+USB_DEVICE_REQUEST mSetDebugFeature = {\r
+ 0x0,\r
+ USB_REQ_SET_FEATURE,\r
+ (UINT16)(0x06),\r
+ 0x0000,\r
+ 0x0\r
+ };\r
+\r
+USB_DEVICE_REQUEST mSetDebugAddress = {\r
+ 0x0,\r
+ USB_REQ_SET_ADDRESS,\r
+ (UINT16)(0x7F),\r
+ 0x0000,\r
+ 0x0\r
+ };\r
+\r
+//\r
+// Usb debug port register file, which is defined at\r
+// EHCI Specification.\r
+//\r
+typedef struct _USB_DEBUG_PORT_REGISTER {\r
+ UINT32 ControlStatus;\r
+ UINT8 TokenPid;\r
+ UINT8 SendPid;\r
+ UINT8 ReceivedPid;\r
+ UINT8 Reserved1;\r
+ UINT8 DataBuffer[8];\r
+ UINT8 UsbEndPoint;\r
+ UINT8 UsbAddress;\r
+ UINT8 Reserved2;\r
+ UINT8 Reserved3;\r
+}USB_DEBUG_PORT_REGISTER;\r
+\r
+#pragma pack(1)\r
+//\r
+// The internal data structure of DEBUG_PORT_HANDLE, which stores some\r
+// important datum which are used across various phases.\r
+//\r
+typedef struct _USB_DEBUG_PORT_HANDLE{\r
+ //\r
+ // The usb debug port memory BAR number in EHCI configuration space.\r
+ //\r
+ UINT8 DebugPortBarNumber;\r
+ UINT8 Reserved;\r
+ //\r
+ // The offset of usb debug port registers in EHCI memory range.\r
+ //\r
+ UINT16 DebugPortOffset;\r
+ //\r
+ // The usb debug port memory BAR address.\r
+ //\r
+ UINTN UsbDebugPortMemoryBase;\r
+ //\r
+ // The EHCI memory BAR address.\r
+ //\r
+ UINTN EhciMemoryBase;\r
+ //\r
+ // The Bulk In endpoint toggle bit.\r
+ //\r
+ UINT8 BulkInToggle;\r
+ //\r
+ // The Bulk Out endpoint toggle bit.\r
+ //\r
+ UINT8 BulkOutToggle;\r
+ //\r
+ // The available data length in the following data buffer.\r
+ //\r
+ UINT8 DataCount;\r
+ //\r
+ // The data buffer. Maximum length is 8 bytes.\r
+ //\r
+ UINT8 Data[8];\r
+} USB_DEBUG_PORT_HANDLE;\r
+#pragma pack()\r
+\r
+//\r
+// The global variable which can be used after memory is ready.\r
+//\r
+USB_DEBUG_PORT_HANDLE mUsbDebugPortHandle;\r
+\r
+/**\r
+ Calculate the usb debug port bar address.\r
+\r
+ @param DebugPortOffset Get usb debug port offset in the usb debug port memory space.\r
+ @param DebugPortBarNumbar Get the bar number at which usb debug port is located.\r
+\r
+ @retval RETURN_UNSUPPORTED The usb host controller does not supported usb debug port capability.\r
+ @retval RETURN_SUCCESS Get bar and offset successfully.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+CalculateUsbDebugPortBar (\r
+ OUT UINT16 *DebugPortOffset,\r
+ OUT UINT8 *DebugPortBarNumbar\r
+ )\r
+{\r
+ UINT16 PciStatus;\r
+ UINT8 CapabilityPtr;\r
+ UINT8 CapabilityId;\r
+\r
+ //\r
+ // Enable Ehci Host Controller MMIO Space.\r
+ //\r
+ PciStatus = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_PRIMARY_STATUS_OFFSET);\r
+\r
+ if ((PciStatus & EFI_PCI_STATUS_CAPABILITY) == 0) {\r
+ //\r
+ // The Pci Device Doesn't Support Capability Pointer.\r
+ //\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Get Pointer To Capability List\r
+ //\r
+ CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + PCI_CAPBILITY_POINTER_OFFSET);\r
+\r
+ //\r
+ // Find Capability ID 0xA, Which Is For Debug Port\r
+ //\r
+ while (CapabilityPtr != 0) {\r
+ CapabilityId = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr);\r
+ if (CapabilityId == PCI_CAPABILITY_ID_DEBUG_PORT) {\r
+ break;\r
+ }\r
+ CapabilityPtr = PciRead8(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 1);\r
+ }\r
+\r
+ //\r
+ // No Debug Port Capability Found\r
+ //\r
+ if (CapabilityPtr == 0) {\r
+ return RETURN_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Get The Base Address Of Debug Port Register In Debug Port Capability Register\r
+ //\r
+ *DebugPortOffset = (UINT16)(PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) & 0x1FFF);\r
+ *DebugPortBarNumbar = (UINT8)((PciRead16(PcdGet32(PcdUsbEhciPciAddress) + CapabilityPtr + 2) >> 13) - 1);\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Do a usb IN transaction by usb debug port.\r
+\r
+ @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
+ @param Buffer Pointer to the buffer receiving data.\r
+ @param Length Number of bytes of the received data.\r
+ @param Token The token PID for each USB transaction.\r
+ @param Addr The usb device address for usb transaction.\r
+ @param Ep The endpoint for usb transaction.\r
+ @param DataToggle The toggle bit used at usb transaction.\r
+\r
+ @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
+ @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
+ @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+UsbDebugPortIn (\r
+ IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
+ IN OUT UINT8 *Buffer,\r
+ OUT UINT8 *Length,\r
+ IN UINT8 Token,\r
+ IN UINT8 Addr,\r
+ IN UINT8 Ep,\r
+ IN UINT8 DataToggle\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ if (Length == NULL) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+ *Length = 0;\r
+\r
+ DebugPortRegister->TokenPid = Token;\r
+ if (DataToggle != 0) {\r
+ DebugPortRegister->SendPid = DATA1_PID;\r
+ } else {\r
+ DebugPortRegister->SendPid = DATA0_PID;\r
+ }\r
+\r
+ DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);\r
+ DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);\r
+\r
+ //\r
+ // Clearing W/R bit to indicate it's a READ operation\r
+ //\r
+ MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~BIT4);\r
+\r
+ //\r
+ // Setting GO bit as well as clearing DONE bit\r
+ //\r
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)BIT5);\r
+\r
+ //\r
+ // Wait for completing the request\r
+ //\r
+ while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & (UINT32)BIT16) == 0);\r
+\r
+ //\r
+ // Check if the request is executed successfully or not.\r
+ //\r
+ if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {\r
+ return RETURN_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Make sure the received data are not beyond the allowable maximum length - 8 byte\r
+ //\r
+ if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
+ return RETURN_DEVICE_ERROR;\r
+ }\r
+\r
+ *Length = (UINT8)(MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & 0xF);\r
+ for (Index = 0; Index < *Length; Index++) {\r
+ Buffer[Index] = DebugPortRegister->DataBuffer[Index];\r
+ }\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Do a usb SETUP/OUT transaction by usb debug port.\r
+\r
+ @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
+ @param Buffer Pointer to the buffer receiving data.\r
+ @param Length Number of bytes of the received data.\r
+ @param Token The token PID for each USB transaction.\r
+ @param Addr The usb device address for usb transaction.\r
+ @param Ep The endpoint for usb transaction.\r
+ @param DataToggle The toggle bit used at usb transaction.\r
+\r
+ @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
+ @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
+ @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+UsbDebugPortOut (\r
+ IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
+ IN UINT8 *Buffer,\r
+ IN UINT8 Length,\r
+ IN UINT8 Token,\r
+ IN UINT8 Addr,\r
+ IN UINT8 Ep,\r
+ IN UINT8 DataToggle\r
+ )\r
+{\r
+ UINT8 Index;\r
+\r
+ if (Length > 8) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ DebugPortRegister->TokenPid = Token;\r
+ if (DataToggle != 0) {\r
+ DebugPortRegister->SendPid = DATA1_PID;\r
+ } else {\r
+ DebugPortRegister->SendPid = DATA0_PID;\r
+ }\r
+ DebugPortRegister->UsbAddress = (UINT8)(Addr & 0x7F);\r
+ DebugPortRegister->UsbEndPoint = (UINT8)(Ep & 0xF);\r
+\r
+ //\r
+ // Fill in the data length and corresponding data.\r
+ //\r
+ MmioAnd32((UINTN)&DebugPortRegister->ControlStatus, (UINT32)~0xF);\r
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, Length & 0xF);\r
+ for (Index = 0; Index < Length; Index++) {\r
+ DebugPortRegister->DataBuffer[Index] = Buffer[Index];\r
+ }\r
+\r
+ //\r
+ // Setting W/R bit to indicate it's a WRITE operation\r
+ //\r
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT4);\r
+ //\r
+ // Setting GO bit as well as clearing DONE bit\r
+ //\r
+ MmioOr32((UINTN)&DebugPortRegister->ControlStatus, BIT5);\r
+\r
+ //\r
+ // Wait for completing the request\r
+ //\r
+ while ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus) & BIT16) == 0);\r
+\r
+ //\r
+ // Check if the request is executed successfully or not.\r
+ //\r
+ if ((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & BIT6) {\r
+ return RETURN_DEVICE_ERROR;\r
+ }\r
+\r
+ //\r
+ // Make sure the sent data are not beyond the allowable maximum length - 8 byte\r
+ //\r
+ if (((MmioRead32((UINTN)&DebugPortRegister->ControlStatus)) & 0xF) > USB_DEBUG_PORT_MAX_PACKET_SIZE) {\r
+ return RETURN_DEVICE_ERROR;\r
+ }\r
+\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+/**\r
+ Do a usb control transfer by usb debug port.\r
+\r
+ @param DebugPortRegister Pointer to the base address of usb debug port register interface.\r
+ @param SetupPacket The token PID for each USB transaction.\r
+ @param Addr The usb device address for usb transaction.\r
+ @param Ep The endpoint for usb transaction.\r
+ @param Data Pointer to the buffer receiving data.\r
+ @param DataLength Number of bytes of the received data.\r
+\r
+ @retval RETURN_SUCCESS The IN transaction is executed successfully.\r
+ @retval RETURN_INVALID_PARAMETER The parameters passed in are invalid.\r
+ @retval RETURN_DEVICE_ERROR The IN transaction comes across error.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+UsbDebugPortControlTransfer (\r
+ IN USB_DEBUG_PORT_REGISTER *DebugPortRegister,\r
+ IN USB_DEVICE_REQUEST *SetupPacket,\r
+ IN UINT8 Addr,\r
+ IN UINT8 Ep,\r
+ OUT UINT8 *Data,\r
+ IN OUT UINT8 *DataLength\r
+ )\r
+{\r
+ RETURN_STATUS Status;\r
+ UINT8 Temp;\r
+\r
+ //\r
+ // Setup Phase\r
+ //\r
+ Status = UsbDebugPortOut(DebugPortRegister, (UINT8 *)SetupPacket, (UINT8)sizeof(USB_DEVICE_REQUEST), SETUP_PID, Addr, Ep, 0);\r
+ if (RETURN_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Data Phase\r
+ //\r
+ if (SetupPacket->Length != 0) {\r
+ if ((SetupPacket->RequestType & BIT7) != 0) {\r
+ //\r
+ // Get Data From Device\r
+ //\r
+ Status = UsbDebugPortIn(DebugPortRegister, Data, DataLength, INPUT_PID, Addr, Ep, 1);\r
+ if (RETURN_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ //\r
+ // Send Data To Device\r
+ //\r
+ Status = UsbDebugPortOut(DebugPortRegister, Data, *DataLength, OUTPUT_PID, Addr, Ep, 1);\r
+ if (RETURN_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Status Phase\r
+ //\r
+ if ((SetupPacket->RequestType & BIT7) != 0) {\r
+ //\r
+ // For READ operation, Data Toggle in Status Phase Should be 1.\r
+ //\r
+ Status = UsbDebugPortOut(DebugPortRegister, NULL, 0, OUTPUT_PID, Addr, Ep, 1);\r
+ } else {\r
+ //\r
+ // For WRITE operation, Data Toggle in Status Phase Should be 1.\r
+ //\r
+ Status = UsbDebugPortIn(DebugPortRegister, NULL, &Temp, INPUT_PID, Addr, Ep, 1);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check if it needs to re-initialize usb debug port hardware.\r
+\r
+ During different phases switch, such as SEC to PEI or PEI to DXE or DXE to SMM, we should check\r
+ whether the usb debug port hardware configuration is changed. Such case can be triggerred by\r
+ Pci bus resource allocation and so on.\r
+\r
+ @param Handle Debug port handle.\r
+\r
+ @retval TRUE The usb debug port hardware configuration is changed.\r
+ @retval FALSE The usb debug port hardware configuration is not changed.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+NeedReinitializeHardware(\r
+ IN USB_DEBUG_PORT_HANDLE *Handle\r
+ )\r
+{\r
+ UINT16 PciCmd;\r
+ UINTN UsbDebugPortMemoryBase;\r
+ UINTN EhciMemoryBase;\r
+ BOOLEAN Status;\r
+ USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
+\r
+ Status = FALSE;\r
+\r
+ EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);\r
+ if (EhciMemoryBase != Handle->EhciMemoryBase) {\r
+ Handle->EhciMemoryBase = EhciMemoryBase;\r
+ Status = TRUE;\r
+ }\r
+\r
+ UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle->DebugPortBarNumber * 4);\r
+ if (UsbDebugPortMemoryBase != Handle->UsbDebugPortMemoryBase) {\r
+ Handle->UsbDebugPortMemoryBase = UsbDebugPortMemoryBase;\r
+ Status = TRUE;\r
+ }\r
+\r
+ //\r
+ // Enable Ehci Memory Space Access\r
+ //\r
+ PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
+ if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
+ Status = TRUE;\r
+ }\r
+\r
+ //\r
+ // Check if the debug port is enabled and owned by myself.\r
+ //\r
+ UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
+ if ((MmioRead32((UINTN)&UsbDebugPortRegister->ControlStatus) &\r
+ (USB_DEBUG_PORT_OWNER | USB_DEBUG_PORT_ENABLE | USB_DEBUG_PORT_IN_USE)) == 0) {\r
+ Status = TRUE;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Initialize usb debug port hardware.\r
+\r
+ 1. reset ehci host controller.\r
+ 2. set right port to debug port.\r
+ 3. find a usb debug device is attached by getting debug device descriptor.\r
+ 4. set address for the usb debug device.\r
+ 5. configure the usb debug device to debug mode.\r
+\r
+ @param Handle Debug port handle.\r
+\r
+ @retval TRUE The usb debug port hardware configuration is changed.\r
+ @retval FALSE The usb debug port hardware configuration is not changed.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+InitializeUsbDebugHardware (\r
+ IN USB_DEBUG_PORT_HANDLE *Handle\r
+)\r
+{\r
+ RETURN_STATUS Status;\r
+ USB_DEBUG_PORT_REGISTER *UsbDebugPortRegister;\r
+ USB_DEBUG_PORT_DESCRIPTOR UsbDebugPortDescriptor;\r
+ UINT16 PciCmd;\r
+ UINT32 *PortStatus;\r
+ UINT32 *UsbCmd;\r
+ UINT32 *UsbStatus;\r
+ UINT32 *UsbHCSParam;\r
+ UINT8 DebugPortNumber;\r
+ UINT8 Length;\r
+\r
+ UsbDebugPortRegister = (USB_DEBUG_PORT_REGISTER *)(Handle->UsbDebugPortMemoryBase + Handle->DebugPortOffset);\r
+ PciCmd = PciRead16 (PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET);\r
+ UsbHCSParam = (UINT32 *)(Handle->EhciMemoryBase + 0x04);\r
+ UsbCmd = (UINT32 *)(Handle->EhciMemoryBase + 0x20);\r
+ UsbStatus = (UINT32 *)(Handle->EhciMemoryBase + 0x24);\r
+\r
+ //\r
+ // initialize the data toggle used by bulk in/out endpoint.\r
+ //\r
+ Handle->BulkInToggle = 0;\r
+ Handle->BulkOutToggle = 0;\r
+\r
+ //\r
+ // Enable Ehci Memory Space Access\r
+ //\r
+ if (((PciCmd & EFI_PCI_COMMAND_MEMORY_SPACE) == 0) || ((PciCmd & EFI_PCI_COMMAND_BUS_MASTER) == 0)) {\r
+ PciCmd |= EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER;\r
+ PciWrite16(PcdGet32(PcdUsbEhciPciAddress) + PCI_COMMAND_OFFSET, PciCmd);\r
+ }\r
+\r
+ //\r
+ // If the host controller is not halted, then halt it.\r
+ //\r
+ if ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0) {\r
+ MmioAnd32((UINTN)UsbCmd, (UINT32)~BIT0);\r
+ while ((MmioRead32((UINTN)UsbStatus) & BIT12) == 0);\r
+ }\r
+ //\r
+ // reset the host controller.\r
+ //\r
+ MmioOr32((UINTN)UsbCmd, BIT1);\r
+ //\r
+ // ensure that the host controller is reset.\r
+ //\r
+ while (MmioRead32((UINTN)UsbCmd) & BIT1);\r
+\r
+ //\r
+ // Start the host controller if it's not running\r
+ //\r
+ if (MmioRead32((UINTN)UsbStatus) & BIT12) {\r
+ MmioOr32((UINTN)UsbCmd, BIT0);\r
+ // ensure that the host controller is started (HALTED bit must be cleared)\r
+ while (MmioRead32((UINTN)UsbStatus) & BIT12);\r
+ }\r
+\r
+ //\r
+ //&