+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.4) ...\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n";\r
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";\r
+\r
+//\r
+// Vector Handoff Info list used by Debug Agent for persist\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent[] = {\r
+ {\r
+ DEBUG_EXCEPT_DIVIDE_ERROR, // Vector 0\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_DEBUG, // Vector 1\r
+ EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_NMI, // Vector 2\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_BREAKPOINT, // Vector 3\r
+ EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_OVERFLOW, // Vector 4\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_BOUND, // Vector 5\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_INVALID_OPCODE, // Vector 6\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_DOUBLE_FAULT, // Vector 8\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_INVALID_TSS, // Vector 10\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_SEG_NOT_PRESENT, // Vector 11\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_STACK_FAULT, // Vector 12\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_GP_FAULT, // Vector 13\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_PAGE_FAULT, // Vector 14\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_FP_ERROR, // Vector 16\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_ALIGNMENT_CHECK, // Vector 17\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_MACHINE_CHECK, // Vector 18\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_EXCEPT_SIMD, // Vector 19\r
+ EFI_VECTOR_HANDOFF_HOOK_BEFORE,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_TIMER_VECTOR, // Vector 32\r
+ EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ DEBUG_MAILBOX_VECTOR, // Vector 33\r
+ EFI_VECTOR_HANDOFF_DO_NOT_HOOK,\r
+ EFI_DEBUG_AGENT_GUID\r
+ },\r
+ {\r
+ 0,\r
+ EFI_VECTOR_HANDOFF_LAST_ENTRY,\r
+ { 0 }\r
+ }\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN mVectorHandoffInfoCount = sizeof (mVectorHandoffInfoDebugAgent) / sizeof (EFI_VECTOR_HANDOFF_INFO);\r
+\r
+/**\r
+ Calculate CRC16 for target data.\r
+\r
+ @param[in] Data The target data.\r
+ @param[in] DataSize The target data size.\r
+ @param[in] Crc Initial CRC.\r
+\r
+ @return UINT16 The CRC16 value.\r
+\r
+**/\r
+UINT16\r
+CalculateCrc16 (\r
+ IN UINT8 *Data,\r
+ IN UINTN DataSize,\r
+ IN UINT16 Crc\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN BitIndex;\r
+\r
+ for (Index = 0; Index < DataSize; Index++) {\r
+ Crc ^= (UINT16)Data[Index];\r
+ for (BitIndex = 0; BitIndex < 8; BitIndex++) {\r
+ if ((Crc & 0x8000) != 0) {\r
+ Crc <<= 1;\r
+ Crc ^= 0x1021;\r
+ } else {\r
+ Crc <<= 1;\r
+ }\r
+ }\r
+ }\r
+ return Crc;\r
+}\r
+\r
+\r
+/**\r
+ Read IDT entry to check if IDT entries are setup by Debug Agent.\r
+\r
+ @retval TRUE IDT entries were setup by Debug Agent.\r
+ @retval FALSE IDT entries were not setup by Debug Agent.\r
+\r
+**/\r
+BOOLEAN\r
+IsDebugAgentInitialzed (\r
+ VOID\r
+ )\r
+{\r
+ UINTN InterruptHandler;\r
+\r
+ InterruptHandler = (UINTN) GetExceptionHandlerInIdtEntry (0);\r
+ if (InterruptHandler >= 4 && *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {\r
+ return TRUE;\r
+ } else {\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Find and report module image info to HOST.\r
+\r
+ @param[in] AlignSize Image aligned size.\r
+\r
+**/\r
+VOID\r
+FindAndReportModuleImageInfo (\r
+ IN UINTN AlignSize\r
+ )\r
+{\r
+ UINTN Pe32Data;\r
+ EFI_IMAGE_DOS_HEADER *DosHdr;\r
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+\r
+ //\r
+ // Find Image Base\r
+ //\r
+ Pe32Data = ((UINTN)mErrorMsgVersionAlert) & ~(AlignSize - 1);\r
+ while (Pe32Data != 0) {\r
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;\r
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+ //\r
+ // DOS image header is present, so read the PE header after the DOS image header.\r
+ //\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+ //\r
+ // Make sure PE header address does not overflow and is less than the initial address.\r
+ //\r
+ if (((UINTN)Hdr.Pe32 > Pe32Data) && ((UINTN)Hdr.Pe32 < (UINTN)mErrorMsgVersionAlert)) {\r
+ if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+ //\r
+ // It's PE image.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // DOS image header is not present, TE header is at the image base.\r
+ //\r
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+ if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&\r
+ ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {\r
+ //\r
+ // It's TE image, it TE header and Machine type match\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Not found the image base, check the previous aligned address\r
+ //\r
+ Pe32Data -= AlignSize;\r
+ }\r
+\r
+ ImageContext.ImageAddress = Pe32Data;\r
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
+}\r
+\r
+/**\r
+ Trigger one software interrupt to debug agent to handle it.\r
+\r
+ @param[in] Signature Software interrupt signature.\r
+\r
+**/\r
+VOID\r
+TriggerSoftInterrupt (\r
+ IN 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
+ Caculate Mailbox checksum and update the checksum field.\r
+\r
+ @param[in] Mailbox Debug Agent Mailbox pointer.\r
+\r
+**/\r
+VOID\r
+UpdateMailboxChecksum (\r
+ IN DEBUG_AGENT_MAILBOX *Mailbox\r
+ )\r
+{\r
+ Mailbox->CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);\r
+}\r
+\r
+/**\r
+ Verify Mailbox checksum.\r
+\r
+ If checksum error, print debug message and run init dead loop.\r
+\r
+ @param[in] Mailbox Debug Agent Mailbox pointer.\r
+\r
+**/\r
+VOID\r
+VerifyMailboxChecksum (\r
+ IN DEBUG_AGENT_MAILBOX *Mailbox\r
+ )\r
+{\r
+ UINT8 CheckSum;\r
+\r
+ CheckSum = CalculateCheckSum8 ((UINT8 *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);\r
+ //\r
+ // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field\r
+ // and ToBeCheckSum field to validate the mail box.\r
+ //\r
+ if (CheckSum != Mailbox->CheckSum && CheckSum != Mailbox->ToBeCheckSum) {\r
+ DEBUG ((EFI_D_ERROR, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));\r
+ DEBUG ((EFI_D_ERROR, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum, Mailbox->CheckSum, Mailbox->ToBeCheckSum));\r
+ CpuDeadLoop ();\r
+ }\r
+}\r