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