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