2 Processor specific parts of the GDB stub
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <GdbStubInternal.h>
13 // Array of exception types that need to be hooked by the debugger
14 // {EFI mapping, GDB mapping}
16 EFI_EXCEPTION_TYPE_ENTRY gExceptionType
[] = {
17 { EXCEPT_IA32_DIVIDE_ERROR
, GDB_SIGFPE
},
18 { EXCEPT_IA32_DEBUG
, GDB_SIGTRAP
},
19 { EXCEPT_IA32_NMI
, GDB_SIGEMT
},
20 { EXCEPT_IA32_BREAKPOINT
, GDB_SIGTRAP
},
21 { EXCEPT_IA32_OVERFLOW
, GDB_SIGSEGV
},
22 { EXCEPT_IA32_BOUND
, GDB_SIGSEGV
},
23 { EXCEPT_IA32_INVALID_OPCODE
, GDB_SIGILL
},
24 { EXCEPT_IA32_DOUBLE_FAULT
, GDB_SIGEMT
},
25 { EXCEPT_IA32_STACK_FAULT
, GDB_SIGSEGV
},
26 { EXCEPT_IA32_GP_FAULT
, GDB_SIGSEGV
},
27 { EXCEPT_IA32_PAGE_FAULT
, GDB_SIGSEGV
},
28 { EXCEPT_IA32_FP_ERROR
, GDB_SIGEMT
},
29 { EXCEPT_IA32_ALIGNMENT_CHECK
, GDB_SIGEMT
},
30 { EXCEPT_IA32_MACHINE_CHECK
, GDB_SIGEMT
}
34 // The offsets of registers SystemContext.
35 // The fields in the array are in the gdb ordering.
38 UINTN gRegisterOffsets
[] = {
39 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Eax
),
40 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Ecx
),
41 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Edx
),
42 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Ebx
),
43 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Esp
),
44 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Ebp
),
45 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Esi
),
46 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Edi
),
47 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Eip
),
48 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Eflags
),
49 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Cs
),
50 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Ss
),
51 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Ds
),
52 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Es
),
53 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Fs
),
54 OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32
, Gs
)
61 IN EFI_SYSTEM_CONTEXT SystemContext
64 Print ((CHAR16
*)L
"EAX: %x ", SystemContext
.SystemContextIa32
->Eax
);
65 Print ((CHAR16
*)L
"ECX: %x ", SystemContext
.SystemContextIa32
->Ecx
);
66 Print ((CHAR16
*)L
"EDX: %x ", SystemContext
.SystemContextIa32
->Edx
);
67 Print ((CHAR16
*)L
"EBX: %x ", SystemContext
.SystemContextIa32
->Ebx
);
68 Print ((CHAR16
*)L
"ESP: %x ", SystemContext
.SystemContextIa32
->Esp
);
69 Print ((CHAR16
*)L
"EBP: %x ", SystemContext
.SystemContextIa32
->Ebp
);
70 Print ((CHAR16
*)L
"ESI: %x ", SystemContext
.SystemContextIa32
->Esi
);
71 Print ((CHAR16
*)L
"EDI: %x ", SystemContext
.SystemContextIa32
->Edi
);
72 Print ((CHAR16
*)L
"EIP: %x\n", SystemContext
.SystemContextIa32
->Eip
);
73 Print ((CHAR16
*)L
"EFlags: %x\n", SystemContext
.SystemContextIa32
->Eflags
);
79 IN EFI_SYSTEM_CONTEXT SystemContext
82 Print ((CHAR16
*)L
"DR0: %x ", SystemContext
.SystemContextIa32
->Dr0
);
83 Print ((CHAR16
*)L
"DR1: %x ", SystemContext
.SystemContextIa32
->Dr1
);
84 Print ((CHAR16
*)L
"DR2: %x ", SystemContext
.SystemContextIa32
->Dr2
);
85 Print ((CHAR16
*)L
"DR3: %x ", SystemContext
.SystemContextIa32
->Dr3
);
86 Print ((CHAR16
*)L
"DR6: %x ", SystemContext
.SystemContextIa32
->Dr6
);
87 Print ((CHAR16
*)L
"DR7: %x\n", SystemContext
.SystemContextIa32
->Dr7
);
92 Return the number of entries in the gExceptionType[]
94 @retval UINTN, the number of entries in the gExceptionType[] array.
101 return sizeof (gExceptionType
)/sizeof (EFI_EXCEPTION_TYPE_ENTRY
);
106 Return the number of entries in the gRegisters[]
108 @retval UINTN, the number of entries (registers) in the gRegisters[] array.
115 return sizeof (gRegisterOffsets
)/sizeof (UINTN
);
120 Check to see if the ISA is supported.
121 ISA = Instruction Set Architecture
123 @retval TRUE if Isa is supported,
128 IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
131 return (BOOLEAN
)(Isa
== IsaIa32
);
136 This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
137 It is, by default, set to find the register pointer of the IA32 member
139 @param SystemContext Register content at time of the exception
140 @param RegNumber The register to which we want to find a pointer
141 @retval the pointer to the RegNumber-th pointer
144 FindPointerToRegister (
145 IN EFI_SYSTEM_CONTEXT SystemContext
,
150 TempPtr
= ((UINT8
*)SystemContext
.SystemContextIa32
) + gRegisterOffsets
[RegNumber
];
151 return (UINTN
*)TempPtr
;
156 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
158 @param SystemContext Register content at time of the exception
159 @param RegNumber the number of the register that we want to read
160 @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
161 @retval the pointer to the next character of the output buffer that is available to be written on.
165 IN EFI_SYSTEM_CONTEXT SystemContext
,
173 while (RegSize
< REG_SIZE
) {
174 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister (SystemContext
, RegNumber
) >> (RegSize
+4)) & 0xf)];
175 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister (SystemContext
, RegNumber
) >> RegSize
) & 0xf)];
176 RegSize
= RegSize
+ 8;
183 Reads the n-th register's value into an output buffer and sends it as a packet
185 @param SystemContext Register content at time of the exception
186 @param InBuffer Pointer to the input buffer received from gdb server
191 IN EFI_SYSTEM_CONTEXT SystemContext
,
196 CHAR8 OutBuffer
[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
197 CHAR8
*OutBufPtr
; // pointer to the output buffer
199 RegNumber
= AsciiStrHexToUintn (&InBuffer
[1]);
201 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount())) {
202 SendError (GDB_EINVALIDREGNUM
);
206 OutBufPtr
= OutBuffer
;
207 OutBufPtr
= BasicReadRegister (SystemContext
, RegNumber
, OutBufPtr
);
209 *OutBufPtr
= '\0'; // the end of the buffer
210 SendPacket(OutBuffer
);
215 Reads the general registers into an output buffer and sends it as a packet
217 @param SystemContext Register content at time of the exception
221 ReadGeneralRegisters (
222 IN EFI_SYSTEM_CONTEXT SystemContext
226 CHAR8 OutBuffer
[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
227 CHAR8
*OutBufPtr
; // pointer to the output buffer
229 OutBufPtr
= OutBuffer
;
230 for (i
= 0 ; i
< MaxRegisterCount() ; i
++) { // there are only 16 registers to read
231 OutBufPtr
= BasicReadRegister (SystemContext
, i
, OutBufPtr
);
234 *OutBufPtr
= '\0'; // the end of the buffer
235 SendPacket(OutBuffer
);
240 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
242 @param SystemContext Register content at time of the exception
243 @param RegNumber the number of the register that we want to write
244 @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
245 @retval the pointer to the next character of the input buffer that can be used
249 IN EFI_SYSTEM_CONTEXT SystemContext
,
255 UINTN TempValue
; // the value transferred from a hex char
256 UINT32 NewValue
; // the new value of the RegNumber-th Register
260 while (RegSize
< REG_SIZE
) {
261 TempValue
= HexCharToInt(*InBufPtr
++);
264 SendError (GDB_EBADMEMDATA
);
268 NewValue
+= (TempValue
<< (RegSize
+4));
269 TempValue
= HexCharToInt(*InBufPtr
++);
272 SendError (GDB_EBADMEMDATA
);
276 NewValue
+= (TempValue
<< RegSize
);
277 RegSize
= RegSize
+ 8;
279 *(FindPointerToRegister (SystemContext
, RegNumber
)) = NewValue
;
285 Writes the new value of n-th register received into the input buffer to the n-th register
287 @param SystemContext Register content at time of the exception
288 @param InBuffer Ponter to the input buffer received from gdb server
293 IN EFI_SYSTEM_CONTEXT SystemContext
,
298 CHAR8 RegNumBuffer
[MAX_REG_NUM_BUF_SIZE
]; // put the 'n..' part of the message into this array
300 CHAR8
*InBufPtr
; // pointer to the input buffer
302 // find the register number to write
303 InBufPtr
= &InBuffer
[1];
304 RegNumBufPtr
= RegNumBuffer
;
305 while (*InBufPtr
!= '=') {
306 *RegNumBufPtr
++ = *InBufPtr
++;
308 *RegNumBufPtr
= '\0';
309 RegNumber
= AsciiStrHexToUintn (RegNumBuffer
);
311 // check if this is a valid Register Number
312 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount())) {
313 SendError (GDB_EINVALIDREGNUM
);
316 InBufPtr
++; // skips the '=' character
317 BasicWriteRegister (SystemContext
, RegNumber
, InBufPtr
);
323 Writes the new values received into the input buffer to the general registers
325 @param SystemContext Register content at time of the exception
326 @param InBuffer Pointer to the input buffer received from gdb server
330 WriteGeneralRegisters (
331 IN EFI_SYSTEM_CONTEXT SystemContext
,
336 CHAR8
*InBufPtr
; /// pointer to the input buffer
338 // check to see if the buffer is the right size which is
339 // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129
340 if (AsciiStrLen(InBuffer
) != 129) { // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
341 //Bad message. Message is not the right length
342 SendError (GDB_EBADBUFSIZE
);
346 InBufPtr
= &InBuffer
[1];
348 // Read the new values for the registers from the input buffer to an array, NewValueArray.
349 // The values in the array are in the gdb ordering
350 for (i
=0; i
< MaxRegisterCount(); i
++) { // there are only 16 registers to write
351 InBufPtr
= BasicWriteRegister (SystemContext
, i
, InBufPtr
);
359 Insert Single Step in the SystemContext
361 @param SystemContext Register content at time of the exception
365 IN EFI_SYSTEM_CONTEXT SystemContext
368 SystemContext
.SystemContextIa32
->Eflags
|= TF_BIT
; //Setting the TF bit.
373 Remove Single Step in the SystemContext
375 @param SystemContext Register content at time of the exception
379 IN EFI_SYSTEM_CONTEXT SystemContext
382 SystemContext
.SystemContextIa32
->Eflags
&= ~TF_BIT
; // clearing the TF bit.
388 Continue. addr is Address to resume. If addr is omitted, resume at current
391 @param SystemContext Register content at time of the exception
396 IN EFI_SYSTEM_CONTEXT SystemContext
,
400 if (PacketData
[1] != '\0') {
401 SystemContext
.SystemContextIa32
->Eip
= AsciiStrHexToUintn (&PacketData
[1]);
407 Single step. addr is the Address at which to resume. If addr is omitted, resume
410 @param SystemContext Register content at time of the exception
415 IN EFI_SYSTEM_CONTEXT SystemContext
,
419 if (PacketData
[1] != '\0') {
420 SystemContext
.SystemContextIa32
->Eip
= AsciiStrHexToUintn (&PacketData
[1]);
423 AddSingleStep (SystemContext
);
428 Returns breakpoint data address from DR0-DR3 based on the input breakpoint number
430 @param SystemContext Register content at time of the exception
431 @param BreakpointNumber Breakpoint number
433 @retval Address Data address from DR0-DR3 based on the breakpoint number.
437 GetBreakpointDataAddress (
438 IN EFI_SYSTEM_CONTEXT SystemContext
,
439 IN UINTN BreakpointNumber
444 if (BreakpointNumber
== 1) {
445 Address
= SystemContext
.SystemContextIa32
->Dr0
;
446 } else if (BreakpointNumber
== 2) {
447 Address
= SystemContext
.SystemContextIa32
->Dr1
;
448 } else if (BreakpointNumber
== 3) {
449 Address
= SystemContext
.SystemContextIa32
->Dr2
;
450 } else if (BreakpointNumber
== 4) {
451 Address
= SystemContext
.SystemContextIa32
->Dr3
;
461 Returns currently detected breakpoint value based on the register DR6 B0-B3 field.
462 If no breakpoint is detected then it returns 0.
464 @param SystemContext Register content at time of the exception
466 @retval {1-4} Currently detected breakpoint value
467 @retval 0 No breakpoint detected.
471 GetBreakpointDetected (
472 IN EFI_SYSTEM_CONTEXT SystemContext
476 UINTN BreakpointNumber
;
478 Dr6
.UintN
= SystemContext
.SystemContextIa32
->Dr6
;
480 if (Dr6
.Bits
.B0
== 1) {
481 BreakpointNumber
= 1;
482 } else if (Dr6
.Bits
.B1
== 1) {
483 BreakpointNumber
= 2;
484 } else if (Dr6
.Bits
.B2
== 1) {
485 BreakpointNumber
= 3;
486 } else if (Dr6
.Bits
.B3
== 1) {
487 BreakpointNumber
= 4;
489 BreakpointNumber
= 0; //No breakpoint detected
492 return BreakpointNumber
;
497 Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite)
498 based on the Breakpoint number
500 @param SystemContext Register content at time of the exception
501 @param BreakpointNumber Breakpoint number
503 @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field
504 For unknown value, it returns NotSupported.
509 IN EFI_SYSTEM_CONTEXT SystemContext
,
510 IN UINTN BreakpointNumber
514 BREAK_TYPE Type
= NotSupported
; //Default is NotSupported type
516 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
518 if (BreakpointNumber
== 1) {
519 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW0
;
520 } else if (BreakpointNumber
== 2) {
521 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW1
;
522 } else if (BreakpointNumber
== 3) {
523 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW2
;
524 } else if (BreakpointNumber
== 4) {
525 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW3
;
533 Parses Length and returns the length which DR7 LENn field accepts.
534 For example: If we receive 1-Byte length then we should return 0.
535 Zero gets written to DR7 LENn field.
537 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
539 @retval Length Appropriate converted values which DR7 LENn field accepts.
547 if (Length
== 1) { //1-Byte length
549 } else if (Length
== 2) { //2-Byte length
551 } else if (Length
== 4) { //4-Byte length
553 } else { //Undefined or 8-byte length
560 Finds the next free debug register. If all the registers are occupied then
561 EFI_OUT_OF_RESOURCES is returned.
563 @param SystemContext Register content at time of the exception
564 @param Register Register value (0 - 3 for the first free debug register)
566 @retval EFI_STATUS Appropriate status value.
570 FindNextFreeDebugRegister (
571 IN EFI_SYSTEM_CONTEXT SystemContext
,
577 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
579 if (Dr7
.Bits
.G0
== 0) {
581 } else if (Dr7
.Bits
.G1
== 0) {
583 } else if (Dr7
.Bits
.G2
== 0) {
585 } else if (Dr7
.Bits
.G3
== 0) {
588 return EFI_OUT_OF_RESOURCES
;
596 Enables the debug register. Writes Address value to appropriate DR0-3 register.
597 Sets LENn, Gn, RWn bits in DR7 register.
599 @param SystemContext Register content at time of the exception
600 @param Register Register value (0 - 3)
601 @param Address Breakpoint address value
602 @param Type Breakpoint type (Instruction, Data write, Data read
605 @retval EFI_STATUS Appropriate status value.
609 EnableDebugRegister (
610 IN EFI_SYSTEM_CONTEXT SystemContext
,
619 //Convert length data
620 Length
= ConvertLengthData (Length
);
622 //For Instruction execution, length should be 0
623 //(Ref. Intel reference manual 18.2.4)
624 if ((Type
== 0) && (Length
!= 0)) {
625 return EFI_INVALID_PARAMETER
;
628 //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
629 //software breakpoint. We should send empty packet in both these cases.
630 if ((Type
== (BREAK_TYPE
)DataRead
) ||
631 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
)) {
632 return EFI_UNSUPPORTED
;
635 //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
636 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
639 SystemContext
.SystemContextIa32
->Dr0
= Address
;
642 Dr7
.Bits
.LEN0
= Length
;
643 } else if (Register
== 1) {
644 SystemContext
.SystemContextIa32
->Dr1
= Address
;
647 Dr7
.Bits
.LEN1
= Length
;
648 } else if (Register
== 2) {
649 SystemContext
.SystemContextIa32
->Dr2
= Address
;
652 Dr7
.Bits
.LEN2
= Length
;
653 } else if (Register
== 3) {
654 SystemContext
.SystemContextIa32
->Dr3
= Address
;
657 Dr7
.Bits
.LEN3
= Length
;
659 return EFI_INVALID_PARAMETER
;
662 //Update Dr7 with appropriate Gn, RWn and LENn bits
663 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
670 Returns register number 0 - 3 for the maching debug register.
671 This function compares incoming Address, Type, Length and
672 if there is a match then it returns the appropriate register number.
673 In case of mismatch, function returns EFI_NOT_FOUND message.
675 @param SystemContext Register content at time of the exception
676 @param Address Breakpoint address value
677 @param Length Breakpoint length value
678 @param Type Breakpoint type (Instruction, Data write,
679 Data read or write etc.)
680 @param Register Register value to be returned
682 @retval EFI_STATUS Appropriate status value.
686 FindMatchingDebugRegister (
687 IN EFI_SYSTEM_CONTEXT SystemContext
,
696 //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
697 //software breakpoint. We should send empty packet in both these cases.
698 if ((Type
== (BREAK_TYPE
)DataRead
) ||
699 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
)) {
700 return EFI_UNSUPPORTED
;
703 //Convert length data
704 Length
= ConvertLengthData(Length
);
706 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
708 if ((Dr7
.Bits
.G0
== 1) &&
709 (Dr7
.Bits
.LEN0
== Length
) &&
710 (Dr7
.Bits
.RW0
== Type
) &&
711 (Address
== SystemContext
.SystemContextIa32
->Dr0
)) {
713 } else if ((Dr7
.Bits
.G1
== 1) &&
714 (Dr7
.Bits
.LEN1
== Length
) &&
715 (Dr7
.Bits
.RW1
== Type
) &&
716 (Address
== SystemContext
.SystemContextIa32
->Dr1
)) {
718 } else if ((Dr7
.Bits
.G2
== 1) &&
719 (Dr7
.Bits
.LEN2
== Length
) &&
720 (Dr7
.Bits
.RW2
== Type
) &&
721 (Address
== SystemContext
.SystemContextIa32
->Dr2
)) {
723 } else if ((Dr7
.Bits
.G3
== 1) &&
724 (Dr7
.Bits
.LEN3
== Length
) &&
725 (Dr7
.Bits
.RW3
== Type
) &&
726 (Address
== SystemContext
.SystemContextIa32
->Dr3
)) {
729 Print ((CHAR16
*)L
"No match found..\n");
730 return EFI_NOT_FOUND
;
738 Disables the particular debug register.
740 @param SystemContext Register content at time of the exception
741 @param Register Register to be disabled
743 @retval EFI_STATUS Appropriate status value.
747 DisableDebugRegister (
748 IN EFI_SYSTEM_CONTEXT SystemContext
,
755 //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
756 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
759 SystemContext
.SystemContextIa32
->Dr0
= Address
;
763 } else if (Register
== 1) {
764 SystemContext
.SystemContextIa32
->Dr1
= Address
;
768 } else if (Register
== 2) {
769 SystemContext
.SystemContextIa32
->Dr2
= Address
;
773 } else if (Register
== 3) {
774 SystemContext
.SystemContextIa32
->Dr3
= Address
;
779 return EFI_INVALID_PARAMETER
;
782 //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
783 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
790 ‘Z1, [addr], [length]’
791 ‘Z2, [addr], [length]’
792 ‘Z3, [addr], [length]’
793 ‘Z4, [addr], [length]’
795 Insert hardware breakpoint/watchpoint at address addr of size length
797 @param SystemContext Register content at time of the exception
798 @param *PacketData Pointer to the Payload data for the packet
804 IN EFI_SYSTEM_CONTEXT SystemContext
,
813 BREAK_TYPE BreakType
= NotSupported
;
816 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
818 SendError ((UINT8
)ErrorCode
);
824 case 0: //Software breakpoint
825 BreakType
= SoftwareBreakpoint
;
828 case 1: //Hardware breakpoint
829 BreakType
= InstructionExecution
;
832 case 2: //Write watchpoint
833 BreakType
= DataWrite
;
836 case 3: //Read watchpoint
837 BreakType
= DataRead
;
840 case 4: //Access watchpoint
841 BreakType
= DataReadWrite
;
845 Print ((CHAR16
*)L
"Insert breakpoint default: %x\n", Type
);
846 SendError (GDB_EINVALIDBRKPOINTTYPE
);
850 // Find next free debug register
851 Status
= FindNextFreeDebugRegister (SystemContext
, &Register
);
852 if (EFI_ERROR(Status
)) {
853 Print ((CHAR16
*)L
"No space left on device\n");
854 SendError (GDB_ENOSPACE
);
858 // Write Address, length data at particular DR register
859 Status
= EnableDebugRegister (SystemContext
, Register
, Address
, Length
, (UINTN
)BreakType
);
860 if (EFI_ERROR(Status
)) {
862 if (Status
== EFI_UNSUPPORTED
) {
863 Print ((CHAR16
*)L
"Not supported\n");
868 Print ((CHAR16
*)L
"Invalid argument\n");
869 SendError (GDB_EINVALIDARG
);
878 ‘z1, [addr], [length]’
879 ‘z2, [addr], [length]’
880 ‘z3, [addr], [length]’
881 ‘z4, [addr], [length]’
883 Remove hardware breakpoint/watchpoint at address addr of size length
885 @param *PacketData Pointer to the Payload data for the packet
891 IN EFI_SYSTEM_CONTEXT SystemContext
,
899 BREAK_TYPE BreakType
= NotSupported
;
903 //Parse breakpoint packet data
904 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
906 SendError ((UINT8
)ErrorCode
);
912 case 0: //Software breakpoint
913 BreakType
= SoftwareBreakpoint
;
916 case 1: //Hardware breakpoint
917 BreakType
= InstructionExecution
;
920 case 2: //Write watchpoint
921 BreakType
= DataWrite
;
924 case 3: //Read watchpoint
925 BreakType
= DataRead
;
928 case 4: //Access watchpoint
929 BreakType
= DataReadWrite
;
933 SendError (GDB_EINVALIDBRKPOINTTYPE
);
937 //Find matching debug register
938 Status
= FindMatchingDebugRegister (SystemContext
, Address
, Length
, (UINTN
)BreakType
, &Register
);
939 if (EFI_ERROR(Status
)) {
941 if (Status
== EFI_UNSUPPORTED
) {
942 Print ((CHAR16
*)L
"Not supported.\n");
947 Print ((CHAR16
*)L
"No matching register found.\n");
948 SendError (GDB_ENOSPACE
);
953 Status
= DisableDebugRegister (SystemContext
, Register
);
954 if (EFI_ERROR(Status
)) {
955 Print ((CHAR16
*)L
"Invalid argument.\n");
956 SendError (GDB_EINVALIDARG
);
965 InitializeProcessor (
981 IN EFI_EXCEPTION_TYPE ExceptionType
,
982 IN OUT EFI_SYSTEM_CONTEXT SystemContext