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