]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
239cf63f6b155ac864a3bc63f7ec26ac4eb1ac4d
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
1 /** @file
2 Commond Debug Agent library implementition. It mainly includes
3 the first C function called by exception/interrupt handlers,
4 read/write debug packet to communication with HOST based on transfer
5 protocol.
6
7 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php.
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "DebugAgent.h"
19 #include "Ia32/DebugException.h"
20
21 CHAR8 mErrorMsgVersionAlert[] = "\rThe SourceLevelDebugPkg you are using requires a newer version of the Intel(R) UDK Debugger Tool.\r\n";
22 CHAR8 mErrorMsgSendInitPacket[] = "\rSend INIT break packet and try to connect the HOST (Intel(R) UDK Debugger Tool v1.3.1) ...\r\n";
23 CHAR8 mErrorMsgConnectOK[] = "HOST connection is successful!\r\n";
24 CHAR8 mErrorMsgConnectFail[] = "HOST connection is failed!\r\n";
25 CHAR8 mWarningMsgIngoreBreakpoint[] = "Ignore break point in SMM for SMI issued during DXE debugging!\r\n";
26
27 //
28 // Vector Handoff Info list used by Debug Agent for persist
29 //
30 EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent[] = {
31 {
32 DEBUG_EXCEPT_DIVIDE_ERROR, // Vector 0
33 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
34 EFI_DEBUG_AGENT_GUID
35 },
36 {
37 DEBUG_EXCEPT_DEBUG, // Vector 1
38 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
39 EFI_DEBUG_AGENT_GUID
40 },
41 {
42 DEBUG_EXCEPT_NMI, // Vector 2
43 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
44 EFI_DEBUG_AGENT_GUID
45 },
46 {
47 DEBUG_EXCEPT_BREAKPOINT, // Vector 3
48 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
49 EFI_DEBUG_AGENT_GUID
50 },
51 {
52 DEBUG_EXCEPT_OVERFLOW, // Vector 4
53 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
54 EFI_DEBUG_AGENT_GUID
55 },
56 {
57 DEBUG_EXCEPT_BOUND, // Vector 5
58 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
59 EFI_DEBUG_AGENT_GUID
60 },
61 {
62 DEBUG_EXCEPT_INVALID_OPCODE, // Vector 6
63 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
64 EFI_DEBUG_AGENT_GUID
65 },
66 {
67 DEBUG_EXCEPT_DOUBLE_FAULT, // Vector 8
68 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
69 EFI_DEBUG_AGENT_GUID
70 },
71 {
72 DEBUG_EXCEPT_INVALID_TSS, // Vector 10
73 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
74 EFI_DEBUG_AGENT_GUID
75 },
76 {
77 DEBUG_EXCEPT_SEG_NOT_PRESENT, // Vector 11
78 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
79 EFI_DEBUG_AGENT_GUID
80 },
81 {
82 DEBUG_EXCEPT_STACK_FAULT, // Vector 12
83 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
84 EFI_DEBUG_AGENT_GUID
85 },
86 {
87 DEBUG_EXCEPT_GP_FAULT, // Vector 13
88 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
89 EFI_DEBUG_AGENT_GUID
90 },
91 {
92 DEBUG_EXCEPT_PAGE_FAULT, // Vector 14
93 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
94 EFI_DEBUG_AGENT_GUID
95 },
96 {
97 DEBUG_EXCEPT_FP_ERROR, // Vector 16
98 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
99 EFI_DEBUG_AGENT_GUID
100 },
101 {
102 DEBUG_EXCEPT_ALIGNMENT_CHECK, // Vector 17
103 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
104 EFI_DEBUG_AGENT_GUID
105 },
106 {
107 DEBUG_EXCEPT_MACHINE_CHECK, // Vector 18
108 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
109 EFI_DEBUG_AGENT_GUID
110 },
111 {
112 DEBUG_EXCEPT_SIMD, // Vector 19
113 EFI_VECTOR_HANDOFF_HOOK_BEFORE,
114 EFI_DEBUG_AGENT_GUID
115 },
116 {
117 DEBUG_TIMER_VECTOR, // Vector 32
118 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
119 EFI_DEBUG_AGENT_GUID
120 },
121 {
122 DEBUG_MAILBOX_VECTOR, // Vector 33
123 EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
124 EFI_DEBUG_AGENT_GUID
125 },
126 {
127 0,
128 EFI_VECTOR_HANDOFF_LAST_ENTRY,
129 { 0 }
130 }
131 };
132
133 UINTN mVectorHandoffInfoCount = sizeof (mVectorHandoffInfoDebugAgent) / sizeof (EFI_VECTOR_HANDOFF_INFO);
134
135 /**
136 Calculate CRC16 for target data.
137
138 @param[in] Data The target data.
139 @param[in] DataSize The target data size.
140 @param[in] Crc Initial CRC.
141
142 @return UINT16 The CRC16 value.
143
144 **/
145 UINT16
146 CalculateCrc16 (
147 IN UINT8 *Data,
148 IN UINTN DataSize,
149 IN UINT16 Crc
150 )
151 {
152 UINTN Index;
153 UINTN BitIndex;
154
155 for (Index = 0; Index < DataSize; Index++) {
156 Crc ^= Data[Index];
157 for (BitIndex = 0; BitIndex < 8; BitIndex++) {
158 if ((Crc & 0x8000) != 0) {
159 Crc <<= 1;
160 Crc ^= 0x1021;
161 } else {
162 Crc <<= 1;
163 }
164 }
165 }
166 return Crc;
167 }
168
169
170 /**
171 Read IDT entry to check if IDT entries are setup by Debug Agent.
172
173 @retval TRUE IDT entries were setup by Debug Agent.
174 @retval FALSE IDT entries were not setup by Debug Agent.
175
176 **/
177 BOOLEAN
178 IsDebugAgentInitialzed (
179 VOID
180 )
181 {
182 UINTN InterruptHandler;
183
184 InterruptHandler = (UINTN) GetExceptionHandlerInIdtEntry (0);
185 if (InterruptHandler >= 4 && *(UINT32 *)(InterruptHandler - 4) == AGENT_HANDLER_SIGNATURE) {
186 return TRUE;
187 } else {
188 return FALSE;
189 }
190 }
191
192 /**
193 Find and report module image info to HOST.
194
195 @param[in] AlignSize Image aligned size.
196
197 **/
198 VOID
199 FindAndReportModuleImageInfo (
200 IN UINTN AlignSize
201 )
202 {
203 UINTN Pe32Data;
204 EFI_IMAGE_DOS_HEADER *DosHdr;
205 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
206 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
207
208 //
209 // Find Image Base
210 //
211 Pe32Data = ((UINTN)mErrorMsgVersionAlert) & ~(AlignSize - 1);
212 while (Pe32Data != 0) {
213 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
214 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
215 //
216 // DOS image header is present, so read the PE header after the DOS image header.
217 // Check if address overflow firstly.
218 //
219 if ((MAX_ADDRESS - (UINTN)DosHdr->e_lfanew) > Pe32Data) {
220 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN)(DosHdr->e_lfanew));
221 if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
222 //
223 // It's PE image.
224 //
225 break;
226 }
227 }
228 } else {
229 //
230 // DOS image header is not present, TE header is at the image base.
231 //
232 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
233 if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&
234 ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {
235 //
236 // It's TE image, it TE header and Machine type match
237 //
238 break;
239 }
240 }
241
242 //
243 // Not found the image base, check the previous aligned address
244 //
245 Pe32Data -= AlignSize;
246 }
247
248 ImageContext.ImageAddress = Pe32Data;
249 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
250 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
251 }
252
253 /**
254 Trigger one software interrupt to debug agent to handle it.
255
256 @param[in] Signature Software interrupt signature.
257
258 **/
259 VOID
260 TriggerSoftInterrupt (
261 IN UINT32 Signature
262 )
263 {
264 UINTN Dr0;
265 UINTN Dr1;
266
267 //
268 // Save Debug Register State
269 //
270 Dr0 = AsmReadDr0 ();
271 Dr1 = AsmReadDr1 ();
272
273 //
274 // DR0 = Signature
275 //
276 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);
277 AsmWriteDr1 (Signature);
278
279 //
280 // Do INT3 to communicate with HOST side
281 //
282 CpuBreakpoint ();
283
284 //
285 // Restore Debug Register State only when Host didn't change it inside exception handler.
286 // Dr registers can only be changed by setting the HW breakpoint.
287 //
288 AsmWriteDr0 (Dr0);
289 AsmWriteDr1 (Dr1);
290
291 }
292
293 /**
294 Caculate Mailbox checksum and update the checksum field.
295
296 @param[in] Mailbox Debug Agent Mailbox pointer.
297
298 **/
299 VOID
300 UpdateMailboxChecksum (
301 IN DEBUG_AGENT_MAILBOX *Mailbox
302 )
303 {
304 Mailbox->CheckSum = CalculateCheckSum8 ((UINT8 *)Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);
305 }
306
307 /**
308 Verify Mailbox checksum.
309
310 If checksum error, print debug message and run init dead loop.
311
312 @param[in] Mailbox Debug Agent Mailbox pointer.
313
314 **/
315 VOID
316 VerifyMailboxChecksum (
317 IN DEBUG_AGENT_MAILBOX *Mailbox
318 )
319 {
320 UINT8 CheckSum;
321
322 CheckSum = CalculateCheckSum8 ((UINT8 *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX) - 2);
323 //
324 // The checksum updating process may be disturbed by hardware SMI, we need to check CheckSum field
325 // and ToBeCheckSum field to validate the mail box.
326 //
327 if (CheckSum != Mailbox->CheckSum && CheckSum != Mailbox->ToBeCheckSum) {
328 DEBUG ((EFI_D_ERROR, "DebugAgent: Mailbox checksum error, stack or heap crashed!\n"));
329 DEBUG ((EFI_D_ERROR, "DebugAgent: CheckSum = %x, Mailbox->CheckSum = %x, Mailbox->ToBeCheckSum = %x\n", CheckSum, Mailbox->CheckSum, Mailbox->ToBeCheckSum));
330 CpuDeadLoop ();
331 }
332 }
333
334 /**
335 Update Mailbox content by index.
336
337 @param[in] Mailbox Debug Agent Mailbox pointer.
338 @param[in] Index Mailbox content index.
339 @param[in] Value Value to be set into Mailbox.
340
341 **/
342 VOID
343 UpdateMailboxContent (
344 IN DEBUG_AGENT_MAILBOX *Mailbox,
345 IN UINTN Index,
346 IN UINT64 Value
347 )
348 {
349 AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);
350 switch (Index) {
351 case DEBUG_MAILBOX_DEBUG_FLAG_INDEX:
352 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugFlag.Uint64, sizeof(UINT64))
353 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT64));
354 Mailbox->DebugFlag.Uint64 = Value;
355 break;
356 case DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX:
357 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->DebugPortHandle, sizeof(UINTN))
358 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));
359 Mailbox->DebugPortHandle = (UINTN) Value;
360 break;
361 case DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX:
362 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->ExceptionBufferPointer, sizeof(UINTN))
363 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINTN));
364 Mailbox->ExceptionBufferPointer = (UINTN) Value;
365 break;
366 case DEBUG_MAILBOX_LAST_ACK:
367 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->LastAck, sizeof(UINT8))
368 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
369 Mailbox->LastAck = (UINT8) Value;
370 break;
371 case DEBUG_MAILBOX_SEQUENCE_NO_INDEX:
372 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->SequenceNo, sizeof(UINT8))
373 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
374 Mailbox->SequenceNo = (UINT8) Value;
375 break;
376 case DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX:
377 Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof(UINT8))
378 - CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
379 Mailbox->HostSequenceNo = (UINT8) Value;
380 break;
381 }
382 UpdateMailboxChecksum (Mailbox);
383 ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);
384 }
385 /**
386 Set debug flag in mailbox.
387
388 @param[in] FlagMask Debug flag mask value.
389 @param[in] FlagValue Debug flag value.
390
391 **/
392 VOID
393 SetDebugFlag (
394 IN UINT64 FlagMask,
395 IN UINT32 FlagValue
396 )
397 {
398 DEBUG_AGENT_MAILBOX *Mailbox;
399 UINT64 Data64;
400
401 Mailbox = GetMailboxPointer ();
402 Data64 = (Mailbox->DebugFlag.Uint64 & ~FlagMask) |
403 (LShiftU64 ((UINT64)FlagValue, LowBitSet64 (FlagMask)) & FlagMask);
404 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_FLAG_INDEX, Data64);
405 }
406
407 /**
408 Get debug flag in mailbox.
409
410 @param[in] FlagMask Debug flag mask value.
411
412 @return Debug flag value.
413
414 **/
415 UINT32
416 GetDebugFlag (
417 IN UINT64 FlagMask
418 )
419 {
420 DEBUG_AGENT_MAILBOX *Mailbox;
421 UINT32 DebugFlag;
422
423 Mailbox = GetMailboxPointer ();
424 DebugFlag = (UINT32) RShiftU64 (Mailbox->DebugFlag.Uint64 & FlagMask, LowBitSet64 (FlagMask));
425
426 return DebugFlag;
427 }
428
429 /**
430 Send a debug message packet to the debug port.
431
432 @param[in] Buffer The debug message.
433 @param[in] Length The length of debug message.
434
435 **/
436 VOID
437 SendDebugMsgPacket (
438 IN CHAR8 *Buffer,
439 IN UINTN Length
440 )
441 {
442 DEBUG_PACKET_HEADER DebugHeader;
443 DEBUG_PORT_HANDLE Handle;
444
445 Handle = GetDebugPortHandle();
446
447 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
448 DebugHeader.Command = DEBUG_COMMAND_PRINT_MESSAGE;
449 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER) + (UINT8) Length;
450 DebugHeader.SequenceNo = 0xEE;
451 DebugHeader.Crc = 0;
452 DebugHeader.Crc = CalculateCrc16 (
453 (UINT8 *)Buffer, Length,
454 CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0)
455 );
456
457 DebugPortWriteBuffer (Handle, (UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER));
458 DebugPortWriteBuffer (Handle, (UINT8 *)Buffer, Length);
459 }
460
461 /**
462 Prints a debug message to the debug port if the specified error level is enabled.
463
464 If any bit in ErrorLevel is also set in Mainbox, then print the message specified
465 by Format and the associated variable argument list to the debug port.
466
467 @param[in] ErrorLevel The error level of the debug message.
468 @param[in] Format Format string for the debug message to print.
469 @param[in] ... Variable argument list whose contents are accessed
470 based on the format string specified by Format.
471
472 **/
473 VOID
474 EFIAPI
475 DebugAgentMsgPrint (
476 IN UINT8 ErrorLevel,
477 IN CHAR8 *Format,
478 ...
479 )
480 {
481 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];
482 VA_LIST Marker;
483
484 //
485 // Check driver debug mask value and global mask
486 //
487 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {
488 return;
489 }
490
491 //
492 // Convert the DEBUG() message to an ASCII String
493 //
494 VA_START (Marker, Format);
495 AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
496 VA_END (Marker);
497
498 SendDebugMsgPacket (Buffer, AsciiStrLen (Buffer));
499 }
500
501 /**
502 Prints a debug message to the debug output device if the specified error level is enabled.
503
504 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
505 GetDebugPrintErrorLevel (), then print the message specified by Format and the
506 associated variable argument list to the debug output device.
507
508 If Format is NULL, then ASSERT().
509
510 @param[in] ErrorLevel The error level of the debug message.
511 @param[in] IsSend Flag of debug message to declare that the data is being sent or being received.
512 @param[in] Data Variable argument list whose contents are accessed
513 @param[in] Length based on the format string specified by Format.
514
515 **/
516 VOID
517 EFIAPI
518 DebugAgentDataMsgPrint (
519 IN UINT8 ErrorLevel,
520 IN BOOLEAN IsSend,
521 IN UINT8 *Data,
522 IN UINT8 Length
523 )
524 {
525 CHAR8 Buffer[DEBUG_DATA_MAXIMUM_REAL_DATA];
526 CHAR8 *DestBuffer;
527 UINTN Index;
528
529 //
530 // Check driver debug mask value and global mask
531 //
532 if ((ErrorLevel & GetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL)) == 0) {
533 return;
534 }
535
536 DestBuffer = Buffer;
537 if (IsSend) {
538 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Sent data [ ");
539 } else {
540 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA, "Received data [ ");
541 }
542
543 Index = 0;
544 while (TRUE) {
545 if (DestBuffer - Buffer > DEBUG_DATA_MAXIMUM_REAL_DATA - 6) {
546 //
547 // If there was no enough space in buffer, send out the debug message,
548 // reserving 6 bytes is for the last data and end characters "]\n".
549 //
550 SendDebugMsgPacket (Buffer, DestBuffer - Buffer);
551 DestBuffer = Buffer;
552 }
553 DestBuffer += AsciiSPrint (DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "%02x ", Data[Index]);
554 Index ++;
555 if (Index >= Length) {
556 //
557 // The last character of debug message has been foramtted in buffer
558 //
559 DestBuffer += AsciiSPrint(DestBuffer, DEBUG_DATA_MAXIMUM_REAL_DATA - (DestBuffer - Buffer), "]\n");
560 SendDebugMsgPacket (Buffer, DestBuffer - Buffer);
561 break;
562 }
563 }
564 }
565
566 /**
567 Read remaing debug packet except for the start symbol
568
569 @param[in] Handle Pointer to Debug Port handle.
570 @param[in, out] DebugHeader Debug header buffer including start symbol.
571
572 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
573 @retval EFI_CRC_ERROR CRC check fail.
574 @retval EFI_TIMEOUT Timeout occurs when reading debug packet.
575
576 **/
577 EFI_STATUS
578 ReadRemainingBreakPacket (
579 IN DEBUG_PORT_HANDLE Handle,
580 IN OUT DEBUG_PACKET_HEADER *DebugHeader
581 )
582 {
583 UINT16 Crc;
584 //
585 // Has received start symbol, try to read the rest part
586 //
587 if (DebugPortReadBuffer (Handle, &DebugHeader->Command, sizeof (DEBUG_PACKET_HEADER) - 1, READ_PACKET_TIMEOUT) == 0) {
588 //
589 // Timeout occur, exit
590 //
591 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Timeout in Debug Timer interrupt\n");
592 return EFI_TIMEOUT;
593 }
594
595 Crc = DebugHeader->Crc;
596 DebugHeader->Crc = 0;
597 if (CalculateCrc16 ((UINT8 *)DebugHeader, DebugHeader->Length, 0) != Crc) {
598 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Debug Timer CRC (%x) against (%x)\n", Crc, CalculateCrc16 ((UINT8 *) &DebugHeader, DebugHeader->Length, 0));
599 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *)DebugHeader, DebugHeader->Length);
600 return EFI_CRC_ERROR;
601 }
602
603 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, DebugHeader->SequenceNo);
604 return EFI_SUCCESS;
605 }
606
607 /**
608 Check if HOST is attached based on Mailbox.
609
610 @retval TRUE HOST is attached.
611 @retval FALSE HOST is not attached.
612
613 **/
614 BOOLEAN
615 IsHostAttached (
616 VOID
617 )
618 {
619 return (BOOLEAN) (GetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED) == 1);
620 }
621
622 /**
623 Set HOST connect flag in Mailbox.
624
625 @param[in] Attached Attach status.
626
627 **/
628 VOID
629 SetHostAttached (
630 IN BOOLEAN Attached
631 )
632 {
633 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Attach status is %d\n", Attached);
634 SetDebugFlag (DEBUG_AGENT_FLAG_HOST_ATTACHED, (UINT32)Attached);
635 }
636
637 /**
638 Set debug setting of Debug Agent in Mailbox.
639
640 @param DebugSetting Pointer to Debug Setting defined by transfer protocol.
641
642 @retval RETURN_SUCCESS The setting is set successfully.
643 @retval RETURN_UNSUPPORTED The Key value is not supported.
644
645 **/
646 RETURN_STATUS
647 SetDebugSetting (
648 IN DEBUG_DATA_SET_DEBUG_SETTING *DebugSetting
649 )
650 {
651 RETURN_STATUS Status;
652
653 Status = RETURN_SUCCESS;
654 switch (DebugSetting->Key) {
655 case DEBUG_AGENT_SETTING_SMM_ENTRY_BREAK:
656 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI, DebugSetting->Value);
657 break;
658 case DEBUG_AGENT_SETTING_PRINT_ERROR_LEVEL:
659 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DebugSetting->Value);
660 break;
661 case DEBUG_AGENT_SETTING_BOOT_SCRIPT_ENTRY_BREAK:
662 SetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT, DebugSetting->Value);
663 break;
664 default:
665 Status = RETURN_UNSUPPORTED;
666 }
667 return Status;
668 }
669
670 /**
671 Exectue GO command.
672
673 @param[in] CpuContext Pointer to saved CPU context.
674
675 **/
676 VOID
677 CommandGo (
678 IN DEBUG_CPU_CONTEXT *CpuContext
679 )
680 {
681 IA32_EFLAGS32 *Eflags;
682
683 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
684 Eflags->Bits.TF = 0;
685 Eflags->Bits.RF = 1;
686 }
687
688 /**
689 Exectue Stepping command.
690
691 @param[in] CpuContext Pointer to saved CPU context.
692
693 **/
694 VOID
695 CommandStepping (
696 IN DEBUG_CPU_CONTEXT *CpuContext
697 )
698 {
699 IA32_EFLAGS32 *Eflags;
700
701 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
702 Eflags->Bits.TF = 1;
703 Eflags->Bits.RF = 1;
704 }
705
706 /**
707 Set debug register for hardware breakpoint.
708
709 @param[in] CpuContext Pointer to saved CPU context.
710 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
711
712 **/
713 VOID
714 SetDebugRegister (
715 IN DEBUG_CPU_CONTEXT *CpuContext,
716 IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint
717 )
718 {
719 UINT8 RegisterIndex;
720 UINTN Dr7Value;
721
722 RegisterIndex = SetHwBreakpoint->Type.Index;
723
724 //
725 // Set debug address
726 //
727 * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;
728
729 Dr7Value = CpuContext->Dr7;
730
731 //
732 // Enable Gx, Lx
733 //
734 Dr7Value |= 0x3 << (RegisterIndex * 2);
735 //
736 // Set RWx and Lenx
737 //
738 Dr7Value &= ~(0xf << (16 + RegisterIndex * 4));
739 Dr7Value |= (UINTN) ((SetHwBreakpoint->Type.Length << 2) | SetHwBreakpoint->Type.Access) << (16 + RegisterIndex * 4);
740 //
741 // Enable GE, LE
742 //
743 Dr7Value |= 0x300;
744
745 CpuContext->Dr7 = Dr7Value;
746 }
747
748 /**
749 Clear debug register for hardware breakpoint.
750
751 @param[in] CpuContext Pointer to saved CPU context.
752 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
753
754 **/
755 VOID
756 ClearDebugRegister (
757 IN DEBUG_CPU_CONTEXT *CpuContext,
758 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint
759 )
760 {
761 if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {
762 CpuContext->Dr0 = 0;
763 CpuContext->Dr7 &= ~(0x3 << 0);
764 }
765 if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {
766 CpuContext->Dr1 = 0;
767 CpuContext->Dr7 &= ~(0x3 << 2);
768 }
769 if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {
770 CpuContext->Dr2 = 0;
771 CpuContext->Dr7 &= ~(0x3 << 4);
772 }
773 if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {
774 CpuContext->Dr3 = 0;
775 CpuContext->Dr7 &= ~(0x3 << 6);
776 }
777 }
778
779
780 /**
781 Return the offset of FP / MMX / XMM registers in the FPU saved state by register index.
782
783 @param[in] Index Register index.
784 @param[out] Width Register width returned.
785
786 @return Offset in the FPU Save State.
787
788 **/
789 UINT16
790 ArchReadFxStatOffset (
791 IN UINT8 Index,
792 OUT UINT8 *Width
793 )
794 {
795 if (Index < SOFT_DEBUGGER_REGISTER_ST0) {
796 switch (Index) {
797 case SOFT_DEBUGGER_REGISTER_FP_FCW:
798 *Width = (UINT8) sizeof (UINT16);
799 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fcw);
800
801 case SOFT_DEBUGGER_REGISTER_FP_FSW:
802 *Width = (UINT8) sizeof (UINT16);
803 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Fsw);
804
805 case SOFT_DEBUGGER_REGISTER_FP_FTW:
806 *Width = (UINT8) sizeof (UINT16);
807 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ftw);
808
809 case SOFT_DEBUGGER_REGISTER_FP_OPCODE:
810 *Width = (UINT8) sizeof (UINT16);
811 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Opcode);
812
813 case SOFT_DEBUGGER_REGISTER_FP_EIP:
814 *Width = (UINT8) sizeof (UINT32);
815 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Eip);
816
817 case SOFT_DEBUGGER_REGISTER_FP_CS:
818 *Width = (UINT8) sizeof (UINT16);
819 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Cs);
820
821 case SOFT_DEBUGGER_REGISTER_FP_DATAOFFSET:
822 *Width = (UINT8) sizeof (UINT32);
823 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, DataOffset);
824
825 case SOFT_DEBUGGER_REGISTER_FP_DS:
826 *Width = (UINT8) sizeof (UINT16);
827 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Ds);
828
829 case SOFT_DEBUGGER_REGISTER_FP_MXCSR:
830 *Width = (UINT8) sizeof (UINT32);
831 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr);
832
833 case SOFT_DEBUGGER_REGISTER_FP_MXCSR_MASK:
834 *Width = (UINT8) sizeof (UINT32);
835 return OFFSET_OF(DEBUG_DATA_FX_SAVE_STATE, Mxcsr_Mask);
836 }
837 }
838
839 if (Index <= SOFT_DEBUGGER_REGISTER_ST7) {
840 *Width = 10;
841 } else if (Index <= SOFT_DEBUGGER_REGISTER_XMM15) {
842 *Width = 16;
843 } else {
844 //
845 // MMX register
846 //
847 *Width = 8;
848 Index -= SOFT_DEBUGGER_REGISTER_MM0 - SOFT_DEBUGGER_REGISTER_ST0;
849 }
850
851 return OFFSET_OF (DEBUG_DATA_FX_SAVE_STATE, St0Mm0) + (Index - SOFT_DEBUGGER_REGISTER_ST0) * 16;
852 }
853
854 /**
855 Return the pointer of the register value in the CPU saved context.
856
857 @param[in] CpuContext Pointer to saved CPU context.
858 @param[in] Index Register index value.
859 @param[out] Width Data width to read.
860
861 @return The pointer in the CPU saved context.
862
863 **/
864 UINT8 *
865 ArchReadRegisterBuffer (
866 IN DEBUG_CPU_CONTEXT *CpuContext,
867 IN UINT8 Index,
868 OUT UINT8 *Width
869 )
870 {
871 UINT8 *Buffer;
872
873 if (Index < SOFT_DEBUGGER_REGISTER_FP_BASE) {
874 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, Dr0) + Index * sizeof (UINTN);
875 *Width = (UINT8) sizeof (UINTN);
876 } else {
877 //
878 // FPU/MMX/XMM registers
879 //
880 Buffer = (UINT8 *) CpuContext + OFFSET_OF (DEBUG_CPU_CONTEXT, FxSaveState) + ArchReadFxStatOffset (Index, Width);
881 }
882
883 return Buffer;
884 }
885
886 /**
887 Send the packet without data to HOST.
888
889 @param[in] CommandType Type of Command.
890 @param[in] SequenceNo Sequence number.
891
892 **/
893 VOID
894 SendPacketWithoutData (
895 IN UINT8 CommandType,
896 IN UINT8 SequenceNo
897 )
898 {
899 DEBUG_PACKET_HEADER DebugHeader;
900 DEBUG_PORT_HANDLE Handle;
901
902 Handle = GetDebugPortHandle();
903
904 DebugHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
905 DebugHeader.Command = CommandType;
906 DebugHeader.Length = sizeof (DEBUG_PACKET_HEADER);
907 DebugHeader.SequenceNo = SequenceNo;
908 DebugHeader.Crc = 0;
909 DebugHeader.Crc = CalculateCrc16 ((UINT8 *)&DebugHeader, sizeof (DEBUG_PACKET_HEADER), 0);
910
911 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) &DebugHeader, DebugHeader.Length);
912 DebugPortWriteBuffer (Handle, (UINT8 *) &DebugHeader, DebugHeader.Length);
913 }
914
915 /**
916 Send acknowledge packet to HOST.
917
918 @param[in] AckCommand Type of Acknowledge packet.
919
920 **/
921 VOID
922 SendAckPacket (
923 IN UINT8 AckCommand
924 )
925 {
926 UINT8 SequenceNo;
927 DEBUG_AGENT_MAILBOX *Mailbox;
928
929 if (AckCommand != DEBUG_COMMAND_OK) {
930 //
931 // This is not ACK OK packet
932 //
933 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Send ACK(%d)\n", AckCommand);
934 }
935 Mailbox = GetMailboxPointer();
936 SequenceNo = Mailbox->HostSequenceNo;
937 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "SendAckPacket: SequenceNo = %x\n", SequenceNo);
938 SendPacketWithoutData (AckCommand, SequenceNo);
939 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_LAST_ACK, AckCommand);
940 }
941
942 /**
943 Receive valid packet from HOST.
944
945 @param[out] InputPacket Buffer to receive packet.
946 @param[out] BreakReceived TRUE means break-in symbol received.
947 FALSE means break-in symbol not received.
948 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
949 TRUE: Compatible packet received.
950 FALSE: Incompatible packet received.
951 @param[in] Timeout Time out value to wait for acknowlege from HOST.
952 The unit is microsecond.
953 @param[in] SkipStartSymbol TRUE: Skip time out when reading start symbol.
954 FALSE: Does not Skip time out when reading start symbol.
955
956 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
957 @retval RETURN_TIMEOUT Timeout occurs.
958
959 **/
960 RETURN_STATUS
961 ReceivePacket (
962 OUT UINT8 *InputPacket,
963 OUT BOOLEAN *BreakReceived,
964 OUT BOOLEAN *IncompatibilityFlag, OPTIONAL
965 IN UINTN Timeout,
966 IN BOOLEAN SkipStartSymbol
967 )
968 {
969 DEBUG_PACKET_HEADER *DebugHeader;
970 UINTN Received;
971 DEBUG_PORT_HANDLE Handle;
972 UINT16 Crc;
973 UINTN TimeoutForStartSymbol;
974
975 Handle = GetDebugPortHandle();
976 if (SkipStartSymbol) {
977 TimeoutForStartSymbol = 0;
978 } else {
979 TimeoutForStartSymbol = Timeout;
980 }
981
982 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacket;
983 while (TRUE) {
984 //
985 // Find the valid start symbol
986 //
987 Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);
988 if (Received < sizeof (DebugHeader->StartSymbol)) {
989 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");
990 return RETURN_TIMEOUT;
991 }
992
993 if (DebugHeader->StartSymbol != DEBUG_STARTING_SYMBOL_NORMAL) {
994 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Invalid start symbol received [%02x]\n", DebugHeader->StartSymbol);
995 continue;
996 }
997
998 //
999 // Read Package header till field Length
1000 //
1001 Received = DebugPortReadBuffer (
1002 Handle,
1003 &DebugHeader->Command,
1004 OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),
1005 Timeout
1006 );
1007 if (Received == 0) {
1008 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");
1009 return RETURN_TIMEOUT;
1010 }
1011 if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {
1012 if (IncompatibilityFlag != NULL) {
1013 //
1014 // This is one old version debug packet format, set Incompatibility flag
1015 //
1016 *IncompatibilityFlag = TRUE;
1017 } else {
1018 //
1019 // Skip the bad small packet
1020 //
1021 continue;
1022 }
1023 } else {
1024 //
1025 // Read the payload data include the CRC field
1026 //
1027 Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);
1028 if (Received == 0) {
1029 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");
1030 return RETURN_TIMEOUT;
1031 }
1032 //
1033 // Calculate the CRC of Debug Packet
1034 //
1035 Crc = DebugHeader->Crc;
1036 DebugHeader->Crc = 0;
1037 if (Crc == CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0)) {
1038 break;
1039 }
1040 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "CRC Error (received CRC is %x)\n", Crc);
1041 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);
1042 }
1043 }
1044
1045 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, FALSE, (UINT8 *) DebugHeader, DebugHeader->Length);
1046
1047 return RETURN_SUCCESS;
1048 }
1049
1050 /**
1051 Receive acknowledge packet OK from HOST in specified time.
1052
1053 @param[in] Command The command type issued by TARGET.
1054 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1055 The unit is microsecond.
1056 @param[out] BreakReceived If BreakReceived is not NULL,
1057 TRUE is retured if break-in symbol received.
1058 FALSE is retured if break-in symbol not received.
1059 @param[out] IncompatibilityFlag If IncompatibilityFlag is not NULL, return
1060 TRUE: Compatible packet received.
1061 FALSE: Incompatible packet received.
1062
1063 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
1064 the type of acknowlege packet saved in Ack.
1065 @retval RETURN_TIMEOUT Specified timeout value was up.
1066
1067 **/
1068 RETURN_STATUS
1069 SendCommandAndWaitForAckOK (
1070 IN UINT8 Command,
1071 IN UINTN Timeout,
1072 OUT BOOLEAN *BreakReceived, OPTIONAL
1073 OUT BOOLEAN *IncompatibilityFlag OPTIONAL
1074 )
1075 {
1076 RETURN_STATUS Status;
1077 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];
1078 DEBUG_PACKET_HEADER *DebugHeader;
1079 UINT8 SequenceNo;
1080 UINT8 HostSequenceNo;
1081 UINT8 RetryCount;
1082
1083 RetryCount = 3;
1084 DebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;
1085 Status = RETURN_TIMEOUT;
1086 while (RetryCount > 0) {
1087 SequenceNo = GetMailboxPointer()->SequenceNo;
1088 HostSequenceNo = GetMailboxPointer()->HostSequenceNo;
1089 SendPacketWithoutData (Command, SequenceNo);
1090 Status = ReceivePacket ((UINT8 *) DebugHeader, BreakReceived, IncompatibilityFlag, Timeout, FALSE);
1091 if (Status == RETURN_TIMEOUT) {
1092 if (Command == DEBUG_COMMAND_INIT_BREAK) {
1093 RetryCount--;
1094 } else {
1095 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout when waiting for ACK packet.\n");
1096 }
1097 continue;
1098 }
1099 ASSERT_EFI_ERROR (Status);
1100 //
1101 // Status == RETURN_SUCCESS
1102 //
1103 if (DebugHeader->Command == DEBUG_COMMAND_OK && DebugHeader->SequenceNo == SequenceNo) {
1104 //
1105 // Received Ack OK
1106 //
1107 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_SEQUENCE_NO_INDEX, ++SequenceNo);
1108 return Status;
1109 }
1110 if (DebugHeader->Command == DEBUG_COMMAND_GO && (DebugHeader->SequenceNo == HostSequenceNo || Command == DEBUG_COMMAND_INIT_BREAK)) {
1111 //
1112 // Received Old GO
1113 //
1114 if (Command == DEBUG_COMMAND_INIT_BREAK) {
1115 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive GO() in last boot\n");
1116 }
1117 SendPacketWithoutData (DEBUG_COMMAND_OK, DebugHeader->SequenceNo);
1118 }
1119 }
1120
1121 ASSERT (Command == DEBUG_COMMAND_INIT_BREAK);
1122 return Status;
1123 }
1124
1125 /**
1126 Get current break cause.
1127
1128 @param[in] Vector Vector value of exception or interrupt.
1129 @param[in] CpuContext Pointer to save CPU context.
1130
1131 @return The type of break cause defined by XXXX
1132
1133 **/
1134 UINT8
1135 GetBreakCause (
1136 IN UINTN Vector,
1137 IN DEBUG_CPU_CONTEXT *CpuContext
1138 )
1139 {
1140 UINT8 Cause;
1141
1142 Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;
1143
1144 switch (Vector) {
1145 case DEBUG_INT1_VECTOR:
1146 case DEBUG_INT3_VECTOR:
1147
1148 if (Vector == DEBUG_INT1_VECTOR) {
1149 //
1150 // INT 1
1151 //
1152 if ((CpuContext->Dr6 & BIT14) != 0) {
1153 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;
1154 //
1155 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
1156 // (right after triggering a breakpoint to report image load/unload).
1157 //
1158 return Cause;
1159
1160 } else {
1161 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;
1162 }
1163 } else {
1164 //
1165 // INT 3
1166 //
1167 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;
1168 }
1169
1170 switch (CpuContext->Dr0) {
1171 case IMAGE_LOAD_SIGNATURE:
1172 case IMAGE_UNLOAD_SIGNATURE:
1173
1174 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {
1175
1176 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?
1177 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);
1178 }
1179 break;
1180
1181 case SOFT_INTERRUPT_SIGNATURE:
1182
1183 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {
1184 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;
1185 CpuContext->Dr0 = 0;
1186 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {
1187 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;
1188 CpuContext->Dr0 = 0;
1189 }
1190 break;
1191
1192 default:
1193 break;
1194
1195 }
1196
1197 break;
1198
1199 case DEBUG_TIMER_VECTOR:
1200 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;
1201 break;
1202
1203 default:
1204 if (Vector < 20) {
1205 if (GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) == 1) {
1206 //
1207 // If stepping command is executing
1208 //
1209 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;
1210 } else {
1211 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;
1212 }
1213 }
1214 break;
1215 }
1216
1217 return Cause;
1218 }
1219
1220 /**
1221 Copy memory from source to destination with specified width.
1222
1223 @param[out] Dest A pointer to the destination buffer of the memory copy.
1224 @param[in] Src A pointer to the source buffer of the memory copy.
1225 @param[in] Count The number of data with specified width to copy from source to destination.
1226 @param[in] Width Data width in byte.
1227
1228 **/
1229 VOID
1230 CopyMemByWidth (
1231 OUT UINT8 *Dest,
1232 IN UINT8 *Src,
1233 IN UINT16 Count,
1234 IN UINT8 Width
1235 )
1236 {
1237 UINT8 *Destination;
1238 UINT8 *Source;
1239 INT8 Step;
1240
1241 if (Src > Dest) {
1242 Destination = Dest;
1243 Source = Src;
1244 Step = Width;
1245 } else {
1246 //
1247 // Copy memory from tail to avoid memory overlap
1248 //
1249 Destination = Dest + (Count - 1) * Width;
1250 Source = Src + (Count - 1) * Width;
1251 Step = -Width;
1252 }
1253
1254 while (Count-- != 0) {
1255 switch (Width) {
1256 case 1:
1257 *(UINT8 *) Destination = MmioRead8 ((UINTN) Source);
1258 break;
1259 case 2:
1260 *(UINT16 *) Destination = MmioRead16 ((UINTN) Source);
1261 break;
1262 case 4:
1263 *(UINT32 *) Destination = MmioRead32 ((UINTN) Source);
1264 break;
1265 case 8:
1266 *(UINT64 *) Destination = MmioRead64 ((UINTN) Source);
1267 break;
1268 default:
1269 ASSERT (FALSE);
1270 }
1271 Source += Step;
1272 Destination += Step;
1273 }
1274 }
1275
1276 /**
1277 Read memory with speicifed width and send packet with response data to HOST.
1278
1279 @param[in] Data Pointer to response data buffer.
1280 @param[in] Count The number of data with specified Width.
1281 @param[in] Width Data width in byte.
1282
1283 @retval RETURN_SUCCESS Response data was sent successfully.
1284
1285 **/
1286 RETURN_STATUS
1287 ReadMemoryAndSendResponsePacket (
1288 IN UINT8 *Data,
1289 IN UINT16 Count,
1290 IN UINT8 Width
1291 )
1292 {
1293 RETURN_STATUS Status;
1294 DEBUG_PACKET_HEADER *DebugHeader;
1295 BOOLEAN LastPacket;
1296 DEBUG_PACKET_HEADER *AckDebugHeader;
1297 UINT8 DebugPacket[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];
1298 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT];
1299 DEBUG_PORT_HANDLE Handle;
1300 UINT8 SequenceNo;
1301 UINTN RemainingDataSize;
1302 UINTN CurrentDataSize;
1303
1304 Handle = GetDebugPortHandle();
1305
1306 //
1307 // Data is appended end of Debug Packet header, make sure data address
1308 // in Debug Packet 8-byte alignment always
1309 //
1310 DebugHeader = (DEBUG_PACKET_HEADER *) (ALIGN_VALUE ((UINTN)&DebugPacket + sizeof (DEBUG_PACKET_HEADER), sizeof (UINT64))
1311 - sizeof (DEBUG_PACKET_HEADER));
1312 DebugHeader->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
1313
1314 RemainingDataSize = Count * Width;
1315 while (TRUE) {
1316 SequenceNo = GetMailboxPointer()->HostSequenceNo;
1317 if (RemainingDataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {
1318 //
1319 // If the remaining data is less one real packet size, this is the last data packet
1320 //
1321 CurrentDataSize = RemainingDataSize;
1322 LastPacket = TRUE;
1323 DebugHeader->Command = DEBUG_COMMAND_OK;
1324 } else {
1325 //
1326 // Data is too larger to be sent in one packet, calculate the actual data size could
1327 // be sent in one Maximum data packet
1328 //
1329 CurrentDataSize = (DEBUG_DATA_MAXIMUM_REAL_DATA / Width) * Width;
1330 LastPacket = FALSE;
1331 DebugHeader->Command = DEBUG_COMMAND_IN_PROGRESS;
1332 }
1333 //
1334 // Construct the rest Debug header
1335 //
1336 DebugHeader->Length = (UINT8)(CurrentDataSize + sizeof (DEBUG_PACKET_HEADER));
1337 DebugHeader->SequenceNo = SequenceNo;
1338 DebugHeader->Crc = 0;
1339 CopyMemByWidth ((UINT8 *)(DebugHeader + 1), Data, (UINT16) CurrentDataSize / Width, Width);
1340 //
1341 // Calculate and fill the checksum, DebugHeader->Crc should be 0 before invoking CalculateCrc16 ()
1342 //
1343 DebugHeader->Crc = CalculateCrc16 ((UINT8 *) DebugHeader, DebugHeader->Length, 0);
1344
1345 DebugAgentDataMsgPrint (DEBUG_AGENT_VERBOSE, TRUE, (UINT8 *) DebugHeader, DebugHeader->Length);
1346
1347 DebugPortWriteBuffer (Handle, (UINT8 *) DebugHeader, DebugHeader->Length);
1348
1349 while (TRUE) {
1350 Status = ReceivePacket (InputPacketBuffer, NULL, NULL, READ_PACKET_TIMEOUT, FALSE);
1351 if (Status == RETURN_TIMEOUT) {
1352 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Timeout in SendDataResponsePacket()\n");
1353 break;
1354 }
1355 AckDebugHeader = (DEBUG_PACKET_HEADER *) InputPacketBuffer;
1356 SequenceNo = AckDebugHeader->SequenceNo;
1357 if (AckDebugHeader->Command == DEBUG_COMMAND_OK &&
1358 SequenceNo == DebugHeader->SequenceNo &&
1359 LastPacket) {
1360 //
1361 // If this is the last packet, return RETURN_SUCCESS.
1362 //
1363 return RETURN_SUCCESS;
1364 }
1365 if ((SequenceNo == (UINT8) (DebugHeader->SequenceNo + 1)) && (AckDebugHeader->Command == DEBUG_COMMAND_CONTINUE)) {
1366 //
1367 // Calculate the rest data size
1368 //
1369 Data += CurrentDataSize;
1370 RemainingDataSize -= CurrentDataSize;
1371 UpdateMailboxContent (GetMailboxPointer(), DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) SequenceNo);
1372 break;
1373 }
1374 if (SequenceNo >= DebugHeader->SequenceNo) {
1375 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Received one old or new command(SequenceNo is %x, last SequenceNo is %x)\n", SequenceNo, DebugHeader->SequenceNo);
1376 break;
1377 }
1378 }
1379 }
1380 }
1381
1382 /**
1383 Send packet with response data to HOST.
1384
1385 @param[in] Data Pointer to response data buffer.
1386 @param[in] DataSize Size of response data in byte.
1387
1388 @retval RETURN_SUCCESS Response data was sent successfully.
1389
1390 **/
1391 RETURN_STATUS
1392 SendDataResponsePacket (
1393 IN UINT8 *Data,
1394 IN UINT16 DataSize
1395 )
1396 {
1397 return ReadMemoryAndSendResponsePacket (Data, DataSize, 1);
1398 }
1399
1400 /**
1401 Send break cause packet to HOST.
1402
1403 @param[in] Vector Vector value of exception or interrutp.
1404 @param[in] CpuContext Pointer to save CPU context.
1405
1406 @retval RETURN_SUCCESS Response data was sent successfully.
1407 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
1408
1409 **/
1410 RETURN_STATUS
1411 SendBreakCausePacket (
1412 IN UINTN Vector,
1413 IN DEBUG_CPU_CONTEXT *CpuContext
1414 )
1415 {
1416 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;
1417
1418 DebugDataBreakCause.StopAddress = CpuContext->Eip;
1419 DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);
1420
1421 return SendDataResponsePacket ((UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));
1422 }
1423
1424 /**
1425 Try to attach the HOST.
1426
1427 Send init break packet to HOST:
1428 If no acknowlege received in specified Timeout, return RETURN_TIMEOUT.
1429 If received acknowlege, check the revision of HOST.
1430 Set Attach Flag if attach successfully.
1431
1432 @param[in] BreakCause Break cause of this break event.
1433 @param[in] Timeout Time out value to wait for acknowlege from HOST.
1434 The unit is microsecond.
1435 @param[out] BreakReceived If BreakReceived is not NULL,
1436 TRUE is retured if break-in symbol received.
1437 FALSE is retured if break-in symbol not received.
1438 **/
1439 RETURN_STATUS
1440 AttachHost (
1441 IN UINT8 BreakCause,
1442 IN UINTN Timeout,
1443 OUT BOOLEAN *BreakReceived
1444 )
1445 {
1446 RETURN_STATUS Status;
1447 DEBUG_PORT_HANDLE Handle;
1448 BOOLEAN IncompatibilityFlag;
1449
1450 IncompatibilityFlag = FALSE;
1451 Handle = GetDebugPortHandle();
1452
1453 //
1454 // Send init break and wait ack in Timeout
1455 //
1456 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgSendInitPacket, AsciiStrLen (mErrorMsgSendInitPacket));
1457 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {
1458 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_INIT_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);
1459 } else {
1460 Status = SendCommandAndWaitForAckOK (DEBUG_COMMAND_ATTACH_BREAK, Timeout, BreakReceived, &IncompatibilityFlag);
1461 }
1462 if (IncompatibilityFlag) {
1463 //
1464 // If the incompatible Debug Packet received, the HOST should be running transfer protocol before DEBUG_AGENT_REVISION.
1465 // It could be UDK Debugger for Windows v1.1/v1.2 or for Linux v0.8/v1.2.
1466 //
1467 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgVersionAlert, AsciiStrLen (mErrorMsgVersionAlert));
1468 CpuDeadLoop ();
1469 }
1470
1471 if (RETURN_ERROR (Status)) {
1472 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectFail, AsciiStrLen (mErrorMsgConnectFail));
1473 } else {
1474 DebugPortWriteBuffer (Handle, (UINT8 *) mErrorMsgConnectOK, AsciiStrLen (mErrorMsgConnectOK));
1475 //
1476 // Set Attach flag
1477 //
1478 SetHostAttached (TRUE);
1479 }
1480 return Status;
1481 }
1482
1483 /**
1484 Send Break point packet to HOST.
1485
1486 Only the first breaking processor could sent BREAK_POINT packet.
1487
1488 @param[in] BreakCause Break cause of this break event.
1489 @param[in] ProcessorIndex Processor index value.
1490 @param[out] BreakReceived If BreakReceived is not NULL,
1491 TRUE is retured if break-in symbol received.
1492 FALSE is retured if break-in symbol not received.
1493
1494 **/
1495 VOID
1496 SendBreakPacketToHost (
1497 IN UINT8 BreakCause,
1498 IN UINT32 ProcessorIndex,
1499 OUT BOOLEAN *BreakReceived
1500 )
1501 {
1502 UINT8 InputCharacter;
1503 DEBUG_PORT_HANDLE Handle;
1504
1505 Handle = GetDebugPortHandle();
1506
1507 if (IsHostAttached ()) {
1508 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Send Break Packet to HOST.\n", ProcessorIndex);
1509 SendCommandAndWaitForAckOK (DEBUG_COMMAND_BREAK_POINT, READ_PACKET_TIMEOUT, BreakReceived, NULL);
1510 } else {
1511 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to attach HOST.\n", ProcessorIndex);
1512 //
1513 // If HOST is not attached, try to attach it firstly.
1514 //
1515 //
1516 // Poll Attach symbols from HOST and ack OK
1517 //
1518 do {
1519 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);
1520 } while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);
1521 SendAckPacket (DEBUG_COMMAND_OK);
1522
1523 //
1524 // Try to attach HOST
1525 //
1526 while (AttachHost (BreakCause, 0, NULL) != RETURN_SUCCESS);
1527
1528 }
1529 }
1530
1531 /**
1532 The main function to process communication with HOST.
1533
1534 It received the command packet from HOST, and sent response data packet to HOST.
1535
1536 @param[in] Vector Vector value of exception or interrutp.
1537 @param[in, out] CpuContext Pointer to saved CPU context.
1538 @param[in] BreakReceived TRUE means break-in symbol received.
1539 FALSE means break-in symbol not received.
1540
1541 **/
1542 VOID
1543 CommandCommunication (
1544 IN UINTN Vector,
1545 IN OUT DEBUG_CPU_CONTEXT *CpuContext,
1546 IN BOOLEAN BreakReceived
1547 )
1548 {
1549 RETURN_STATUS Status;
1550 UINT8 InputPacketBuffer[DEBUG_DATA_UPPER_LIMIT + sizeof (UINT64) - 1];
1551 DEBUG_PACKET_HEADER *DebugHeader;
1552 UINT8 Width;
1553 UINT8 Data8;
1554 UINT32 Data32;
1555 UINT64 Data64;
1556 DEBUG_DATA_READ_MEMORY *MemoryRead;
1557 DEBUG_DATA_WRITE_MEMORY *MemoryWrite;
1558 DEBUG_DATA_READ_IO *IoRead;
1559 DEBUG_DATA_WRITE_IO *IoWrite;
1560 DEBUG_DATA_READ_REGISTER *RegisterRead;
1561 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;
1562 UINT8 *RegisterBuffer;
1563 DEBUG_DATA_READ_MSR *MsrRegisterRead;
1564 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;
1565 DEBUG_DATA_CPUID *Cpuid;
1566 DEBUG_DATA_RESPONSE_CPUID CpuidResponse;
1567 DEBUG_DATA_SEARCH_SIGNATURE *SearchSignature;
1568 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;
1569 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;
1570 DEBUG_DATA_SET_VIEWPOINT *SetViewPoint;
1571 BOOLEAN HaltDeferred;
1572 UINT32 ProcessorIndex;
1573 DEBUG_PORT_HANDLE Handle;
1574 DEBUG_AGENT_EXCEPTION_BUFFER AgentExceptionBuffer;
1575 UINT32 IssuedViewPoint;
1576 DEBUG_AGENT_MAILBOX *Mailbox;
1577 UINT8 *AlignedDataPtr;
1578
1579 ProcessorIndex = 0;
1580 IssuedViewPoint = 0;
1581 HaltDeferred = BreakReceived;
1582
1583 if (MultiProcessorDebugSupport()) {
1584 ProcessorIndex = GetProcessorIndex ();
1585 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
1586 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {
1587 //
1588 // Only the current view processor could set AgentInProgress Flag.
1589 //
1590 IssuedViewPoint = ProcessorIndex;
1591 }
1592 }
1593
1594 if (IssuedViewPoint == ProcessorIndex) {
1595 //
1596 // Set AgentInProgress Flag.
1597 //
1598 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 1);
1599 }
1600
1601 Handle = GetDebugPortHandle();
1602
1603 while (TRUE) {
1604
1605 if (MultiProcessorDebugSupport()) {
1606 //
1607 // Check if the current processor is HOST view point
1608 //
1609 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {
1610 if (mDebugMpContext.RunCommandSet) {
1611 //
1612 // If HOST view point sets RUN flag, run GO command to leave
1613 //
1614 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
1615 CommandGo (CpuContext);
1616 break;
1617 } else {
1618 //
1619 // Run into loop again
1620 //
1621 CpuPause ();
1622 continue;
1623 }
1624 }
1625 }
1626
1627 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1628
1629 DebugHeader =(DEBUG_PACKET_HEADER *) InputPacketBuffer;
1630
1631 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "TARGET: Try to get command from HOST...\n");
1632 Status = ReceivePacket ((UINT8 *)DebugHeader, &BreakReceived, NULL, READ_PACKET_TIMEOUT, TRUE);
1633 if (Status != RETURN_SUCCESS || (DebugHeader->Command & DEBUG_COMMAND_RESPONSE) != 0) {
1634 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command[%x] sequenceno[%x] returned status is [%x] \n", DebugHeader->Command, DebugHeader->SequenceNo, Status);
1635 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Get command failed or it's response packet not expected! \n");
1636 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1637 continue;
1638 }
1639
1640 Mailbox = GetMailboxPointer ();
1641 if (DebugHeader->SequenceNo == Mailbox->HostSequenceNo) {
1642 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "TARGET: Receive one old command[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
1643 SendAckPacket (Mailbox->LastAck);
1644 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1645 continue;
1646 } else if (DebugHeader->SequenceNo == (UINT8) (Mailbox->HostSequenceNo + 1)) {
1647 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, (UINT8) DebugHeader->SequenceNo);
1648 } else {
1649 DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "Receive one invalid comamnd[%x] agaist command[%x]\n", DebugHeader->SequenceNo, Mailbox->HostSequenceNo);
1650 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1651 continue;
1652 }
1653
1654 //
1655 // Save CPU content before executing HOST commond
1656 //
1657 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_EXCEPTION_BUFFER_POINTER_INDEX, (UINT64)(UINTN) &AgentExceptionBuffer.JumpBuffer);
1658 if (SetJump (&AgentExceptionBuffer.JumpBuffer) != 0) {
1659 //
1660 // If HOST command failed, continue to wait for HOST's next command
1661 // If needed, agent could send exception info to HOST.
1662 //
1663 SendAckPacket (DEBUG_COMMAND_ABORT);
1664 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1665 continue;
1666 }
1667
1668 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Processor[%x]:Received one command(%x)\n", mDebugMpContext.ViewPointIndex, DebugHeader->Command);
1669
1670 switch (DebugHeader->Command) {
1671
1672 case DEBUG_COMMAND_HALT:
1673 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
1674 HaltDeferred = TRUE;
1675 BreakReceived = FALSE;
1676 Status = RETURN_SUCCESS;
1677 break;
1678
1679 case DEBUG_COMMAND_RESET:
1680 SendAckPacket (DEBUG_COMMAND_OK);
1681 SendAckPacket (DEBUG_COMMAND_OK);
1682 SendAckPacket (DEBUG_COMMAND_OK);
1683 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1684
1685 ResetCold ();
1686 //
1687 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
1688 // PCD can be used if 2 seconds isn't long enough for some platforms.
1689 //
1690 MicroSecondDelay (2000000);
1691 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, Mailbox->HostSequenceNo + 1);
1692 SendAckPacket (DEBUG_COMMAND_TIMEOUT);
1693 SendAckPacket (DEBUG_COMMAND_TIMEOUT);
1694 SendAckPacket (DEBUG_COMMAND_TIMEOUT);
1695 break;
1696
1697 case DEBUG_COMMAND_GO:
1698 CommandGo (CpuContext);
1699 //
1700 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1701 // If HOST changed Dr0 before GO, we will not change Dr0 here
1702 //
1703 Data8 = GetBreakCause (Vector, CpuContext);
1704 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
1705 CpuContext->Dr0 = 0;
1706 }
1707 //
1708 // Clear Stepping Flag
1709 //
1710 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 0);
1711
1712 if (!HaltDeferred) {
1713 //
1714 // If no HALT command received when being in-active mode
1715 //
1716 if (MultiProcessorDebugSupport()) {
1717 Data32 = FindNextPendingBreakCpu ();
1718 if (Data32 != -1) {
1719 //
1720 // If there are still others processors being in break state,
1721 // send OK packet to HOST to finish this go command
1722 //
1723 SendAckPacket (DEBUG_COMMAND_OK);
1724 CpuPause ();
1725 //
1726 // Set current view to the next breaking processor
1727 //
1728 mDebugMpContext.ViewPointIndex = Data32;
1729 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;
1730 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);
1731 //
1732 // Send break packet to HOST to let HOST break again
1733 //
1734 SendBreakPacketToHost (DEBUG_DATA_BREAK_CAUSE_UNKNOWN, mDebugMpContext.BreakAtCpuIndex, &BreakReceived);
1735 //
1736 // Continue to run into loop to read command packet from HOST
1737 //
1738 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1739 break;
1740 }
1741
1742 //
1743 // If no else processor break, set stop bitmask,
1744 // and set Running flag for all processors.
1745 //
1746 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
1747 SetCpuRunningFlag (TRUE);
1748 CpuPause ();
1749 //
1750 // Wait for all processors are in running state
1751 //
1752 while (TRUE) {
1753 if (IsAllCpuRunning ()) {
1754 break;
1755 }
1756 }
1757 //
1758 // Set BSP to be current view point.
1759 //
1760 SetDebugViewPoint (mDebugMpContext.BspIndex);
1761 CpuPause ();
1762 //
1763 // Clear breaking processor index and running flag
1764 //
1765 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
1766 SetCpuRunningFlag (FALSE);
1767 }
1768
1769 //
1770 // Send OK packet to HOST to finish this go command
1771 //
1772 SendAckPacket (DEBUG_COMMAND_OK);
1773
1774 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1775
1776 if (!IsHostAttached()) {
1777 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_SEQUENCE_NO_INDEX, 0);
1778 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX, 0);
1779 }
1780 return;
1781
1782 } else {
1783 //
1784 // If reveived HALT command, need to defer the GO command
1785 //
1786 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);
1787 HaltDeferred = FALSE;
1788
1789 Vector = DEBUG_TIMER_VECTOR;
1790 }
1791 break;
1792
1793 case DEBUG_COMMAND_BREAK_CAUSE:
1794
1795 if (MultiProcessorDebugSupport() && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
1796 Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);
1797
1798 } else {
1799 Status = SendBreakCausePacket (Vector, CpuContext);
1800 }
1801
1802 break;
1803
1804 case DEBUG_COMMAND_SET_HW_BREAKPOINT:
1805 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));
1806 SendAckPacket (DEBUG_COMMAND_OK);
1807 break;
1808
1809 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:
1810 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));
1811 SendAckPacket (DEBUG_COMMAND_OK);
1812 break;
1813
1814 case DEBUG_COMMAND_SINGLE_STEPPING:
1815 CommandStepping (CpuContext);
1816 //
1817 // Clear Dr0 to avoid to be recognized as IMAGE_LOAD/_UNLOAD again when hitting a breakpoint after GO
1818 // If HOST changed Dr0 before GO, we will not change Dr0 here
1819 //
1820 Data8 = GetBreakCause (Vector, CpuContext);
1821 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
1822 CpuContext->Dr0 = 0;
1823 }
1824
1825 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
1826 //
1827 // Set Stepping Flag
1828 //
1829 SetDebugFlag (DEBUG_AGENT_FLAG_STEPPING, 1);
1830 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
1831 //
1832 // Executing stepping command directly without sending ACK packet,
1833 // ACK packet will be sent after stepping done.
1834 //
1835 return;
1836
1837 case DEBUG_COMMAND_SET_SW_BREAKPOINT:
1838 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);
1839 Data8 = *(UINT8 *) (UINTN) Data64;
1840 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;
1841 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));
1842 break;
1843
1844 case DEBUG_COMMAND_READ_MEMORY:
1845 MemoryRead = (DEBUG_DATA_READ_MEMORY *) (DebugHeader + 1);
1846 Status = ReadMemoryAndSendResponsePacket ((UINT8 *) (UINTN) MemoryRead->Address, MemoryRead->Count, MemoryRead->Width);
1847 break;
1848
1849 case DEBUG_COMMAND_WRITE_MEMORY:
1850 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY *) (DebugHeader + 1);
1851 //
1852 // Copy data into one memory with 8-byte alignment address
1853 //
1854 AlignedDataPtr = ALIGN_POINTER ((UINT8 *) &MemoryWrite->Data, sizeof (UINT64));
1855 if (AlignedDataPtr != (UINT8 *) &MemoryWrite->Data) {
1856 CopyMem (AlignedDataPtr, (UINT8 *) &MemoryWrite->Data, MemoryWrite->Count * MemoryWrite->Width);
1857 }
1858 CopyMemByWidth ((UINT8 *) (UINTN) MemoryWrite->Address, AlignedDataPtr, MemoryWrite->Count, MemoryWrite->Width);
1859 SendAckPacket (DEBUG_COMMAND_OK);
1860 break;
1861
1862 case DEBUG_COMMAND_READ_IO:
1863 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);
1864 switch (IoRead->Width) {
1865 case 1:
1866 Data64 = IoRead8 ((UINTN) IoRead->Port);
1867 break;
1868 case 2:
1869 Data64 = IoRead16 ((UINTN) IoRead->Port);
1870 break;
1871 case 4:
1872 Data64 = IoRead32 ((UINTN) IoRead->Port);
1873 break;
1874 case 8:
1875 Data64 = IoRead64 ((UINTN) IoRead->Port);
1876 break;
1877 default:
1878 Data64 = (UINT64) -1;
1879 }
1880 Status = SendDataResponsePacket ((UINT8 *) &Data64, IoRead->Width);
1881 break;
1882
1883 case DEBUG_COMMAND_WRITE_IO:
1884 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);
1885 switch (IoWrite->Width) {
1886 case 1:
1887 Data64 = IoWrite8 ((UINTN) IoWrite->Port, *(UINT8 *) &IoWrite->Data);
1888 break;
1889 case 2:
1890 Data64 = IoWrite16 ((UINTN) IoWrite->Port, *(UINT16 *) &IoWrite->Data);
1891 break;
1892 case 4:
1893 Data64 = IoWrite32 ((UINTN) IoWrite->Port, *(UINT32 *) &IoWrite->Data);
1894 break;
1895 case 8:
1896 Data64 = IoWrite64 ((UINTN) IoWrite->Port, *(UINT64 *) &IoWrite->Data);
1897 break;
1898 default:
1899 Data64 = (UINT64) -1;
1900 }
1901 SendAckPacket (DEBUG_COMMAND_OK);
1902 break;
1903
1904 case DEBUG_COMMAND_READ_ALL_REGISTERS:
1905 Status = SendDataResponsePacket ((UINT8 *) CpuContext, sizeof (*CpuContext));
1906 break;
1907
1908 case DEBUG_COMMAND_READ_REGISTER:
1909 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);
1910
1911 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_MAX) {
1912 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, &Width);
1913 Status = SendDataResponsePacket (RegisterBuffer, Width);
1914 } else {
1915 Status = RETURN_UNSUPPORTED;
1916 }
1917 break;
1918
1919 case DEBUG_COMMAND_WRITE_REGISTER:
1920 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);
1921 if (RegisterWrite->Index <= SOFT_DEBUGGER_REGISTER_MAX) {
1922 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterWrite->Index, &Width);
1923 ASSERT (Width == RegisterWrite->Length);
1924 CopyMem (RegisterBuffer, RegisterWrite->Data, Width);
1925 SendAckPacket (DEBUG_COMMAND_OK);
1926 } else {
1927 Status = RETURN_UNSUPPORTED;
1928 }
1929 break;
1930
1931 case DEBUG_COMMAND_ARCH_MODE:
1932 Data8 = DEBUG_ARCH_SYMBOL;
1933 Status = SendDataResponsePacket ((UINT8 *) &Data8, (UINT16) sizeof (UINT8));
1934 break;
1935
1936 case DEBUG_COMMAND_READ_MSR:
1937 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);
1938 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);
1939 Status = SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (UINT64));
1940 break;
1941
1942 case DEBUG_COMMAND_WRITE_MSR:
1943 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);
1944 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);
1945 SendAckPacket (DEBUG_COMMAND_OK);
1946 break;
1947
1948 case DEBUG_COMMAND_SET_DEBUG_SETTING:
1949 Status = SetDebugSetting ((DEBUG_DATA_SET_DEBUG_SETTING *)(DebugHeader + 1));
1950 if (Status == RETURN_SUCCESS) {
1951 SendAckPacket (DEBUG_COMMAND_OK);
1952 }
1953 break;
1954
1955 case DEBUG_COMMAND_GET_REVISION:
1956 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;
1957 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;
1958 Status = SendDataResponsePacket ((UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));
1959 break;
1960
1961 case DEBUG_COMMAND_GET_EXCEPTION:
1962 Exception.ExceptionNum = (UINT8) Vector;
1963 Exception.ExceptionData = (UINT32) CpuContext->ExceptionData;
1964 Status = SendDataResponsePacket ((UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));
1965 break;
1966
1967 case DEBUG_COMMAND_SET_VIEWPOINT:
1968 SetViewPoint = (DEBUG_DATA_SET_VIEWPOINT *) (DebugHeader + 1);
1969 if (MultiProcessorDebugSupport()) {
1970 if (IsCpuStopped (SetViewPoint->ViewPoint)) {
1971 SetDebugViewPoint (SetViewPoint->ViewPoint);
1972 SendAckPacket (DEBUG_COMMAND_OK);
1973 } else {
1974 //
1975 // If CPU is not halted
1976 //
1977 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
1978 }
1979 } else if (SetViewPoint->ViewPoint == 0) {
1980 SendAckPacket (DEBUG_COMMAND_OK);
1981
1982 } else {
1983 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
1984 }
1985
1986 break;
1987
1988 case DEBUG_COMMAND_GET_VIEWPOINT:
1989 Data32 = mDebugMpContext.ViewPointIndex;
1990 SendDataResponsePacket((UINT8 *) &Data32, (UINT16) sizeof (UINT32));
1991 break;
1992
1993 case DEBUG_COMMAND_MEMORY_READY:
1994 Data8 = (UINT8) GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY);
1995 SendDataResponsePacket (&Data8, (UINT16) sizeof (UINT8));
1996 break;
1997
1998 case DEBUG_COMMAND_DETACH:
1999 SetHostAttached (FALSE);
2000 SendAckPacket (DEBUG_COMMAND_OK);
2001 break;
2002
2003 case DEBUG_COMMAND_CPUID:
2004 Cpuid = (DEBUG_DATA_CPUID *) (DebugHeader + 1);
2005 AsmCpuidEx (
2006 Cpuid->Eax, Cpuid->Ecx,
2007 &CpuidResponse.Eax, &CpuidResponse.Ebx,
2008 &CpuidResponse.Ecx, &CpuidResponse.Edx
2009 );
2010 SendDataResponsePacket ((UINT8 *) &CpuidResponse, (UINT16) sizeof (CpuidResponse));
2011 break;
2012
2013 case DEBUG_COMMAND_SEARCH_SIGNATURE:
2014 SearchSignature = (DEBUG_DATA_SEARCH_SIGNATURE *) (DebugHeader + 1);
2015 if ((SearchSignature->Alignment != 0) &&
2016 (SearchSignature->Alignment == GetPowerOfTwo32 (SearchSignature->Alignment))
2017 ) {
2018 if (SearchSignature->Positive) {
2019 for (
2020 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start, SearchSignature->Alignment);
2021 Data64 <= SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength;
2022 Data64 += SearchSignature->Alignment
2023 ) {
2024 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {
2025 break;
2026 }
2027 }
2028 if (Data64 > SearchSignature->Start + SearchSignature->Count - SearchSignature->DataLength) {
2029 Data64 = (UINT64) -1;
2030 }
2031 } else {
2032 for (
2033 Data64 = ALIGN_VALUE ((UINTN) SearchSignature->Start - SearchSignature->Alignment, SearchSignature->Alignment);
2034 Data64 >= SearchSignature->Start - SearchSignature->Count;
2035 Data64 -= SearchSignature->Alignment
2036 ) {
2037 if (CompareMem ((VOID *) (UINTN) Data64, &SearchSignature->Data, SearchSignature->DataLength) == 0) {
2038 break;
2039 }
2040 }
2041 if (Data64 < SearchSignature->Start - SearchSignature->Count) {
2042 Data64 = (UINT64) -1;
2043 }
2044 }
2045 SendDataResponsePacket ((UINT8 *) &Data64, (UINT16) sizeof (Data64));
2046 } else {
2047 Status = RETURN_UNSUPPORTED;
2048 }
2049 break;
2050
2051 default:
2052 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
2053 break;
2054 }
2055
2056 if (Status == RETURN_UNSUPPORTED) {
2057 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
2058 } else if (Status != RETURN_SUCCESS) {
2059 SendAckPacket (DEBUG_COMMAND_ABORT);
2060 }
2061
2062 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2063 CpuPause ();
2064 }
2065 }
2066
2067 /**
2068 C function called in interrupt handler.
2069
2070 @param[in] Vector Vector value of exception or interrutp.
2071 @param[in] CpuContext Pointer to save CPU context.
2072
2073 **/
2074 VOID
2075 EFIAPI
2076 InterruptProcess (
2077 IN UINT32 Vector,
2078 IN DEBUG_CPU_CONTEXT *CpuContext
2079 )
2080 {
2081 UINT8 InputCharacter;
2082 UINT8 BreakCause;
2083 UINTN SavedEip;
2084 BOOLEAN BreakReceived;
2085 UINT32 ProcessorIndex;
2086 UINT32 CurrentDebugTimerInitCount;
2087 DEBUG_PORT_HANDLE Handle;
2088 UINT8 Data8;
2089 UINT8 *Al;
2090 UINT32 IssuedViewPoint;
2091 DEBUG_AGENT_EXCEPTION_BUFFER *ExceptionBuffer;
2092
2093 ProcessorIndex = 0;
2094 IssuedViewPoint = 0;
2095 BreakReceived = FALSE;
2096
2097 if (mSkipBreakpoint) {
2098 //
2099 // If Skip Breakpoint flag is set, means communication is disturbed by hardware SMI, we need to ignore the break points in SMM
2100 //
2101 if ((Vector == DEBUG_INT1_VECTOR) || (Vector == DEBUG_INT3_VECTOR)) {
2102 DebugPortWriteBuffer (GetDebugPortHandle(), (UINT8 *) mWarningMsgIngoreBreakpoint, AsciiStrLen (mWarningMsgIngoreBreakpoint));
2103 return;
2104 }
2105 }
2106
2107 if (MultiProcessorDebugSupport()) {
2108 ProcessorIndex = GetProcessorIndex ();
2109 //
2110 // If this processor has alreay halted before, need to check it later
2111 //
2112 if (IsCpuStopped (ProcessorIndex)) {
2113 IssuedViewPoint = ProcessorIndex;
2114 }
2115 }
2116
2117 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {
2118 //
2119 // Check if this exception is issued by Debug Agent itself
2120 // If yes, fill the debug agent exception buffer and LongJump() back to
2121 // the saved CPU content in CommandCommunication()
2122 //
2123 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {
2124 DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "Debug agent meet one Exception, ExceptionNum is %d, EIP = 0x%x.\n", Vector, (UINTN)CpuContext->Eip);
2125 ExceptionBuffer = (DEBUG_AGENT_EXCEPTION_BUFFER *) (UINTN) GetMailboxPointer()->ExceptionBufferPointer;
2126 ExceptionBuffer->ExceptionContent.ExceptionNum = (UINT8) Vector;
2127 ExceptionBuffer->ExceptionContent.ExceptionData = (UINT32) CpuContext->ExceptionData;
2128 LongJump ((BASE_LIBRARY_JUMP_BUFFER *)(UINTN)(ExceptionBuffer), 1);
2129 }
2130 }
2131
2132 if (MultiProcessorDebugSupport()) {
2133 //
2134 // If RUN commmand is executing, wait for it done.
2135 //
2136 while (mDebugMpContext.RunCommandSet) {
2137 CpuPause ();
2138 }
2139 }
2140
2141 Handle = GetDebugPortHandle();
2142 BreakCause = GetBreakCause (Vector, CpuContext);
2143 switch (Vector) {
2144 case DEBUG_INT1_VECTOR:
2145 case DEBUG_INT3_VECTOR:
2146 switch (BreakCause) {
2147 case DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET:
2148 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
2149 //
2150 // Try to connect HOST, return if fails
2151 //
2152 break;
2153 }
2154 CommandCommunication (Vector, CpuContext, BreakReceived);
2155 break;
2156
2157 case DEBUG_DATA_BREAK_CAUSE_STEPPING:
2158 //
2159 // Stepping is finished, send Ack package.
2160 //
2161 if (MultiProcessorDebugSupport()) {
2162 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
2163 }
2164 SendAckPacket (DEBUG_COMMAND_OK);
2165 CommandCommunication (Vector, CpuContext, BreakReceived);
2166 break;
2167
2168 case DEBUG_DATA_BREAK_CAUSE_MEMORY_READY:
2169 //
2170 // Memory is ready
2171 //
2172 SendCommandAndWaitForAckOK (DEBUG_COMMAND_MEMORY_READY, READ_PACKET_TIMEOUT, &BreakReceived, NULL);
2173 CommandCommunication (Vector, CpuContext, BreakReceived);
2174 break;
2175
2176 case DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD:
2177 case DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD:
2178 //
2179 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
2180 //
2181 Al = ArchReadRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, &Data8);
2182 *Al = DEBUG_AGENT_IMAGE_CONTINUE;
2183
2184 if (!IsHostAttached ()) {
2185 //
2186 // If HOST is not connected for image load/unload, return
2187 //
2188 break;
2189 }
2190 //
2191 // Continue to run the following common code
2192 //
2193
2194 case DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT:
2195 case DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT:
2196 default:
2197 //
2198 // Send Break packet to HOST
2199 //
2200 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2201 //
2202 // Only the first breaking processor could send BREAK_POINT to HOST
2203 //
2204 if (IsFirstBreakProcessor (ProcessorIndex)) {
2205 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
2206 }
2207 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2208
2209 if (Vector == DEBUG_INT3_VECTOR) {
2210 //
2211 // go back address located "0xCC"
2212 //
2213 CpuContext->Eip--;
2214 SavedEip = CpuContext->Eip;
2215 CommandCommunication (Vector, CpuContext, BreakReceived);
2216 if ((SavedEip == CpuContext->Eip) &&
2217 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {
2218 //
2219 // If this is not a software breakpoint set by HOST,
2220 // restore EIP
2221 //
2222 CpuContext->Eip++;
2223 }
2224 } else {
2225 CommandCommunication (Vector, CpuContext, BreakReceived);
2226 }
2227 break;
2228 }
2229
2230 break;
2231
2232 case DEBUG_TIMER_VECTOR:
2233
2234 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2235
2236 if (MultiProcessorDebugSupport()) {
2237 if (IsBsp (ProcessorIndex)) {
2238 //
2239 // If current processor is BSP, check Apic timer's init count if changed,
2240 // it may be re-written when switching BSP.
2241 // If it changed, re-initialize debug timer
2242 //
2243 CurrentDebugTimerInitCount = GetApicTimerInitCount ();
2244 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
2245 InitializeDebugTimer ();
2246 }
2247 }
2248
2249 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
2250 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2251 //
2252 // If current processor is not BSP or this is one IPI sent by AP
2253 //
2254 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {
2255 CommandCommunication (Vector, CpuContext, FALSE);
2256 }
2257
2258 //
2259 // Clear EOI before exiting interrupt process routine.
2260 //
2261 SendApicEoi ();
2262 break;
2263 }
2264 }
2265
2266 //
2267 // Only BSP could run here
2268 //
2269 while (TRUE) {
2270 //
2271 // If there is data in debug port, will check whether it is break(attach/break-in) symbol,
2272 // If yes, go into communication mode with HOST.
2273 // If no, exit interrupt process.
2274 //
2275 if (DebugReadBreakSymbol (Handle, &InputCharacter) == EFI_NOT_FOUND) {
2276 break;
2277 }
2278
2279 if ((!IsHostAttached () && (InputCharacter == DEBUG_STARTING_SYMBOL_ATTACH)) ||
2280 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_HALT)) ||
2281 (IsHostAttached () && (InputCharacter == DEBUG_COMMAND_GO))
2282 ) {
2283 DebugAgentMsgPrint (DEBUG_AGENT_VERBOSE, "Received data [%02x]\n", InputCharacter);
2284 //
2285 // Ack OK for break-in symbol
2286 //
2287 SendAckPacket (DEBUG_COMMAND_OK);
2288
2289 //
2290 // If receive GO command in Debug Timer, means HOST may lost ACK packet before.
2291 //
2292 if (InputCharacter == DEBUG_COMMAND_GO) {
2293 break;
2294 }
2295
2296 if (!IsHostAttached ()) {
2297 //
2298 // Try to attach HOST, if no ack received after 200ms, return
2299 //
2300 if (AttachHost (BreakCause, READ_PACKET_TIMEOUT, &BreakReceived) != RETURN_SUCCESS) {
2301 break;
2302 }
2303 }
2304
2305 if (MultiProcessorDebugSupport()) {
2306 if(FindNextPendingBreakCpu () != -1) {
2307 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
2308 } else {
2309 HaltOtherProcessors (ProcessorIndex);
2310 }
2311 }
2312 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2313 CommandCommunication (Vector, CpuContext, BreakReceived);
2314 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2315 break;
2316 }
2317 }
2318
2319 //
2320 // Clear EOI before exiting interrupt process routine.
2321 //
2322 SendApicEoi ();
2323
2324 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2325
2326 break;
2327
2328 default:
2329 if (Vector <= DEBUG_EXCEPT_SIMD) {
2330 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
2331 //
2332 // Stepping is finished, send Ack package.
2333 //
2334 if (MultiProcessorDebugSupport()) {
2335 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
2336 }
2337 SendAckPacket (DEBUG_COMMAND_OK);
2338 } else {
2339 //
2340 // Exception occurs, send Break packet to HOST
2341 //
2342 AcquireMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2343 //
2344 // Only the first breaking processor could send BREAK_POINT to HOST
2345 //
2346 if (IsFirstBreakProcessor (ProcessorIndex)) {
2347 SendBreakPacketToHost (BreakCause, ProcessorIndex, &BreakReceived);
2348 }
2349 ReleaseMpSpinLock (&mDebugMpContext.DebugPortSpinLock);
2350 }
2351
2352 CommandCommunication (Vector, CpuContext, BreakReceived);
2353 }
2354 break;
2355 }
2356
2357 if (MultiProcessorDebugSupport()) {
2358 //
2359 // Clear flag and wait for all processors run here
2360 //
2361 SetIpiSentByApFlag (FALSE);
2362 while (mDebugMpContext.RunCommandSet) {
2363 CpuPause ();
2364 }
2365
2366 //
2367 // Only current (view) processor could clean up AgentInProgress flag.
2368 //
2369 if (mDebugMpContext.ViewPointIndex == ProcessorIndex) {
2370 IssuedViewPoint = mDebugMpContext.ViewPointIndex;
2371 }
2372 }
2373
2374 if (IssuedViewPoint == ProcessorIndex && GetDebugFlag (DEBUG_AGENT_FLAG_STEPPING) != 1) {
2375 //
2376 // If the command is not stepping, clean up AgentInProgress flag
2377 //
2378 SetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS, 0);
2379 }
2380
2381 return;
2382 }
2383