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
15 EFI_EXCEPTION_TYPE_ENTRY gExceptionType
[] = {
16 { EXCEPT_X64_DIVIDE_ERROR
, GDB_SIGFPE
},
17 { EXCEPT_X64_DEBUG
, GDB_SIGTRAP
},
18 { EXCEPT_X64_NMI
, GDB_SIGEMT
},
19 { EXCEPT_X64_BREAKPOINT
, GDB_SIGTRAP
},
20 { EXCEPT_X64_OVERFLOW
, GDB_SIGSEGV
},
21 { EXCEPT_X64_BOUND
, GDB_SIGSEGV
},
22 { EXCEPT_X64_INVALID_OPCODE
, GDB_SIGILL
},
23 { EXCEPT_X64_DOUBLE_FAULT
, GDB_SIGEMT
},
24 { EXCEPT_X64_STACK_FAULT
, GDB_SIGSEGV
},
25 { EXCEPT_X64_GP_FAULT
, GDB_SIGSEGV
},
26 { EXCEPT_X64_PAGE_FAULT
, GDB_SIGSEGV
},
27 { EXCEPT_X64_FP_ERROR
, GDB_SIGEMT
},
28 { EXCEPT_X64_ALIGNMENT_CHECK
, GDB_SIGEMT
},
29 { EXCEPT_X64_MACHINE_CHECK
, GDB_SIGEMT
}
33 // The offsets of registers SystemContextX64.
34 // The fields in the array are in the gdb ordering.
35 // HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs
37 UINTN gRegisterOffsets
[] = {
38 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rax
),
39 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rcx
),
40 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rdx
),
41 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rbx
),
42 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rsp
),
43 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rbp
),
44 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rsi
),
45 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rdi
),
46 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rip
),
47 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rflags
),
48 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Cs
),
49 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Ss
),
50 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Ds
),
51 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Es
),
52 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Fs
),
53 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Gs
),
54 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R8
),
55 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R9
),
56 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R10
),
57 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R11
),
58 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R12
),
59 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R13
),
60 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R14
),
61 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R15
)
66 Return the number of entries in the gExceptionType[]
68 @retval UINTN, the number of entries in the gExceptionType[] array.
75 return sizeof (gExceptionType
)/sizeof (EFI_EXCEPTION_TYPE_ENTRY
);
80 Return the number of entries in the gRegisters[]
82 @retval UINTN, the number of entries (registers) in the gRegisters[] array.
89 return sizeof (gRegisterOffsets
)/sizeof (UINTN
);
94 Check to see if the ISA is supported.
95 ISA = Instruction Set Architecture
97 @retval TRUE if Isa is supported
101 IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
104 return (BOOLEAN
)(Isa
== IsaX64
);
109 This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
110 It is, by default, set to find the register pointer of the X64 member
111 @param SystemContext Register content at time of the exception
112 @param RegNumber The register to which we want to find a pointer
113 @retval the pointer to the RegNumber-th pointer
116 FindPointerToRegister(
117 IN EFI_SYSTEM_CONTEXT SystemContext
,
122 TempPtr
= ((UINT8
*)SystemContext
.SystemContextX64
) + gRegisterOffsets
[RegNumber
];
123 return (UINTN
*)TempPtr
;
128 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
129 @param SystemContext Register content at time of the exception
130 @param RegNumber the number of the register that we want to read
131 @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
132 @retval the pointer to the next character of the output buffer that is available to be written on.
136 IN EFI_SYSTEM_CONTEXT SystemContext
,
144 while (RegSize
< 64) {
145 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister(SystemContext
, RegNumber
) >> (RegSize
+4)) & 0xf)];
146 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister(SystemContext
, RegNumber
) >> RegSize
) & 0xf)];
147 RegSize
= RegSize
+ 8;
154 Reads the n-th register's value into an output buffer and sends it as a packet
155 @param SystemContext Register content at time of the exception
156 @param InBuffer Pointer to the input buffer received from gdb server
160 IN EFI_SYSTEM_CONTEXT SystemContext
,
165 CHAR8 OutBuffer
[17]; // 1 reg=16 hex chars, and the end '\0' (escape seq)
166 CHAR8
*OutBufPtr
; // pointer to the output buffer
168 RegNumber
= AsciiStrHexToUintn (&InBuffer
[1]);
170 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount())) {
171 SendError (GDB_EINVALIDREGNUM
);
175 OutBufPtr
= OutBuffer
;
176 OutBufPtr
= BasicReadRegister(SystemContext
, RegNumber
, OutBufPtr
);
178 *OutBufPtr
= '\0'; // the end of the buffer
179 SendPacket (OutBuffer
);
184 Reads the general registers into an output buffer and sends it as a packet
186 @param SystemContext Register content at time of the exception
190 ReadGeneralRegisters (
191 IN EFI_SYSTEM_CONTEXT SystemContext
195 CHAR8 OutBuffer
[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
196 CHAR8
*OutBufPtr
; // pointer to the output buffer
198 OutBufPtr
= OutBuffer
;
199 for(i
= 0 ; i
< MaxRegisterCount() ; i
++) { // there are only 24 registers to read
200 OutBufPtr
= BasicReadRegister(SystemContext
, i
, OutBufPtr
);
203 *OutBufPtr
= '\0'; // the end of the buffer
204 SendPacket (OutBuffer
);
209 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
211 @param SystemContext Register content at time of the exception
212 @param RegNumber the number of the register that we want to write
213 @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
214 @retval the pointer to the next character of the input buffer that can be used
218 IN EFI_SYSTEM_CONTEXT SystemContext
,
224 UINTN TempValue
; // the value transferred from a hex char
225 UINT64 NewValue
; // the new value of the RegNumber-th Register
229 while (RegSize
< 64) {
230 TempValue
= HexCharToInt(*InBufPtr
++);
233 SendError (GDB_EBADMEMDATA
);
237 NewValue
+= (TempValue
<< (RegSize
+4));
238 TempValue
= HexCharToInt(*InBufPtr
++);
241 SendError (GDB_EBADMEMDATA
);
245 NewValue
+= (TempValue
<< RegSize
);
246 RegSize
= RegSize
+ 8;
248 *(FindPointerToRegister(SystemContext
, RegNumber
)) = NewValue
;
254 Writes the new value of n-th register received into the input buffer to the n-th register
256 @param SystemContext Register content at time of the exception
257 @param InBuffer Ponter to the input buffer received from gdb server
262 IN EFI_SYSTEM_CONTEXT SystemContext
,
267 CHAR8 RegNumBuffer
[MAX_REG_NUM_BUF_SIZE
]; // put the 'n..' part of the message into this array
269 CHAR8
*InBufPtr
; // pointer to the input buffer
271 // find the register number to write
272 InBufPtr
= &InBuffer
[1];
273 RegNumBufPtr
= RegNumBuffer
;
274 while (*InBufPtr
!= '=') {
275 *RegNumBufPtr
++ = *InBufPtr
++;
277 *RegNumBufPtr
= '\0';
278 RegNumber
= AsciiStrHexToUintn (RegNumBuffer
);
280 // check if this is a valid Register Number
281 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount())) {
282 SendError (GDB_EINVALIDREGNUM
);
285 InBufPtr
++; // skips the '=' character
286 BasicWriteRegister (SystemContext
, RegNumber
, InBufPtr
);
292 Writes the new values received into the input buffer to the general registers
294 @param SystemContext Register content at time of the exception
295 @param InBuffer Pointer to the input buffer received from gdb server
299 WriteGeneralRegisters (
300 IN EFI_SYSTEM_CONTEXT SystemContext
,
305 CHAR8
*InBufPtr
; /// pointer to the input buffer
307 // check to see if the buffer is the right size which is
308 // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385
309 if (AsciiStrLen(InBuffer
) != 385) { // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
310 //Bad message. Message is not the right length
311 SendError (GDB_EBADBUFSIZE
);
315 InBufPtr
= &InBuffer
[1];
317 // Read the new values for the registers from the input buffer to an array, NewValueArray.
318 // The values in the array are in the gdb ordering
319 for(i
=0; i
< MaxRegisterCount(); i
++) { // there are only 16 registers to write
320 InBufPtr
= BasicWriteRegister(SystemContext
, i
, InBufPtr
);
328 Insert Single Step in the SystemContext
330 @param SystemContext Register content at time of the exception
334 IN EFI_SYSTEM_CONTEXT SystemContext
337 SystemContext
.SystemContextX64
->Rflags
|= TF_BIT
; //Setting the TF bit.
343 Remove Single Step in the SystemContext
345 @param SystemContext Register content at time of the exception
349 IN EFI_SYSTEM_CONTEXT SystemContext
352 SystemContext
.SystemContextX64
->Rflags
&= ~TF_BIT
; // clearing the TF bit.
358 Continue. addr is Address to resume. If addr is omitted, resume at current
361 @param SystemContext Register content at time of the exception
366 IN EFI_SYSTEM_CONTEXT SystemContext
,
370 if (PacketData
[1] != '\0') {
371 SystemContext
.SystemContextX64
->Rip
= AsciiStrHexToUintn(&PacketData
[1]);
377 Single step. addr is the Address at which to resume. If addr is omitted, resume
380 @param SystemContext Register content at time of the exception
385 IN EFI_SYSTEM_CONTEXT SystemContext
,
389 if (PacketData
[1] != '\0') {
390 SystemContext
.SystemContextX64
->Rip
= AsciiStrHexToUintn (&PacketData
[1]);
393 AddSingleStep (SystemContext
);
398 Returns breakpoint data address from DR0-DR3 based on the input breakpoint
401 @param SystemContext Register content at time of the exception
402 @param BreakpointNumber Breakpoint number
404 @retval Address Data address from DR0-DR3 based on the
409 GetBreakpointDataAddress (
410 IN EFI_SYSTEM_CONTEXT SystemContext
,
411 IN UINTN BreakpointNumber
416 if (BreakpointNumber
== 1) {
417 Address
= SystemContext
.SystemContextIa32
->Dr0
;
418 } else if (BreakpointNumber
== 2) {
419 Address
= SystemContext
.SystemContextIa32
->Dr1
;
420 } else if (BreakpointNumber
== 3) {
421 Address
= SystemContext
.SystemContextIa32
->Dr2
;
422 } else if (BreakpointNumber
== 4) {
423 Address
= SystemContext
.SystemContextIa32
->Dr3
;
432 Returns currently detected breakpoint value based on the register
434 If no breakpoint is detected then it returns 0.
436 @param SystemContext Register content at time of the exception
438 @retval {1-4} Currently detected breakpoint value
439 @retval 0 No breakpoint detected.
443 GetBreakpointDetected (
444 IN EFI_SYSTEM_CONTEXT SystemContext
448 UINTN BreakpointNumber
;
450 Dr6
.UintN
= SystemContext
.SystemContextIa32
->Dr6
;
452 if (Dr6
.Bits
.B0
== 1) {
453 BreakpointNumber
= 1;
454 } else if (Dr6
.Bits
.B1
== 1) {
455 BreakpointNumber
= 2;
456 } else if (Dr6
.Bits
.B2
== 1) {
457 BreakpointNumber
= 3;
458 } else if (Dr6
.Bits
.B3
== 1) {
459 BreakpointNumber
= 4;
461 BreakpointNumber
= 0; //No breakpoint detected
464 return BreakpointNumber
;
468 Returns Breakpoint type (InstructionExecution, DataWrite, DataRead
469 or DataReadWrite) based on the Breakpoint number
471 @param SystemContext Register content at time of the exception
472 @param BreakpointNumber Breakpoint number
474 @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn
475 field. For unknown value, it returns NotSupported.
480 IN EFI_SYSTEM_CONTEXT SystemContext
,
481 IN UINTN BreakpointNumber
485 BREAK_TYPE Type
= NotSupported
; //Default is NotSupported type
487 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
489 if (BreakpointNumber
== 1) {
490 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW0
;
491 } else if (BreakpointNumber
== 2) {
492 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW1
;
493 } else if (BreakpointNumber
== 3) {
494 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW2
;
495 } else if (BreakpointNumber
== 4) {
496 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW3
;
504 Parses Length and returns the length which DR7 LENn field accepts.
505 For example: If we receive 1-Byte length then we should return 0.
506 Zero gets written to DR7 LENn field.
508 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
510 @retval Length Appropriate converted values which DR7 LENn field accepts.
518 if (Length
== 1) { //1-Byte length
520 } else if (Length
== 2) { //2-Byte length
522 } else if (Length
== 4) { //4-Byte length
524 } else { //Undefined or 8-byte length
531 Finds the next free debug register. If all the registers are occupied then
532 EFI_OUT_OF_RESOURCES is returned.
534 @param SystemContext Register content at time of the exception
535 @param Register Register value (0 - 3 for the first free debug register)
537 @retval EFI_STATUS Appropriate status value.
541 FindNextFreeDebugRegister (
542 IN EFI_SYSTEM_CONTEXT SystemContext
,
548 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
550 if (Dr7
.Bits
.G0
== 0) {
552 } else if (Dr7
.Bits
.G1
== 0) {
554 } else if (Dr7
.Bits
.G2
== 0) {
556 } else if (Dr7
.Bits
.G3
== 0) {
559 return EFI_OUT_OF_RESOURCES
;
567 Enables the debug register. Writes Address value to appropriate DR0-3 register.
568 Sets LENn, Gn, RWn bits in DR7 register.
570 @param SystemContext Register content at time of the exception
571 @param Register Register value (0 - 3)
572 @param Address Breakpoint address value
573 @param Type Breakpoint type (Instruction, Data write,
574 Data read or write etc.)
576 @retval EFI_STATUS Appropriate status value.
580 EnableDebugRegister (
581 IN EFI_SYSTEM_CONTEXT SystemContext
,
590 //Convert length data
591 Length
= ConvertLengthData (Length
);
593 //For Instruction execution, length should be 0
594 //(Ref. Intel reference manual 18.2.4)
595 if ((Type
== 0) && (Length
!= 0)) {
596 return EFI_INVALID_PARAMETER
;
599 //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
600 //software breakpoint. We should send empty packet in both these cases.
601 if ((Type
== (BREAK_TYPE
)DataRead
) ||
602 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
)) {
603 return EFI_UNSUPPORTED
;
606 //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
607 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
610 SystemContext
.SystemContextIa32
->Dr0
= Address
;
613 Dr7
.Bits
.LEN0
= Length
;
614 } else if (Register
== 1) {
615 SystemContext
.SystemContextIa32
->Dr1
= Address
;
618 Dr7
.Bits
.LEN1
= Length
;
619 } else if (Register
== 2) {
620 SystemContext
.SystemContextIa32
->Dr2
= Address
;
623 Dr7
.Bits
.LEN2
= Length
;
624 } else if (Register
== 3) {
625 SystemContext
.SystemContextIa32
->Dr3
= Address
;
628 Dr7
.Bits
.LEN3
= Length
;
630 return EFI_INVALID_PARAMETER
;
633 //Update Dr7 with appropriate Gn, RWn and LENn bits
634 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
641 Returns register number 0 - 3 for the maching debug register.
642 This function compares incoming Address, Type, Length and
643 if there is a match then it returns the appropriate register number.
644 In case of mismatch, function returns EFI_NOT_FOUND message.
646 @param SystemContext Register content at time of the exception
647 @param Address Breakpoint address value
648 @param Length Breakpoint length value
649 @param Type Breakpoint type (Instruction, Data write, Data read
651 @param Register Register value to be returned
653 @retval EFI_STATUS Appropriate status value.
657 FindMatchingDebugRegister (
658 IN EFI_SYSTEM_CONTEXT SystemContext
,
667 //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
668 //software breakpoint. We should send empty packet in both these cases.
669 if ((Type
== (BREAK_TYPE
)DataRead
) ||
670 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
)) {
671 return EFI_UNSUPPORTED
;
674 //Convert length data
675 Length
= ConvertLengthData(Length
);
677 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
679 if ((Dr7
.Bits
.G0
== 1) &&
680 (Dr7
.Bits
.LEN0
== Length
) &&
681 (Dr7
.Bits
.RW0
== Type
) &&
682 (Address
== SystemContext
.SystemContextIa32
->Dr0
)) {
684 } else if ((Dr7
.Bits
.G1
== 1) &&
685 (Dr7
.Bits
.LEN1
== Length
) &&
686 (Dr7
.Bits
.RW1
== Type
) &&
687 (Address
== SystemContext
.SystemContextIa32
->Dr1
)) {
689 } else if ((Dr7
.Bits
.G2
== 1) &&
690 (Dr7
.Bits
.LEN2
== Length
) &&
691 (Dr7
.Bits
.RW2
== Type
) &&
692 (Address
== SystemContext
.SystemContextIa32
->Dr2
)) {
694 } else if ((Dr7
.Bits
.G3
== 1) &&
695 (Dr7
.Bits
.LEN3
== Length
) &&
696 (Dr7
.Bits
.RW3
== Type
) &&
697 (Address
== SystemContext
.SystemContextIa32
->Dr3
)) {
700 Print ((CHAR16
*)L
"No match found..\n");
701 return EFI_NOT_FOUND
;
709 Disables the particular debug register.
711 @param SystemContext Register content at time of the exception
712 @param Register Register to be disabled
714 @retval EFI_STATUS Appropriate status value.
718 DisableDebugRegister (
719 IN EFI_SYSTEM_CONTEXT SystemContext
,
726 //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
727 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
730 SystemContext
.SystemContextIa32
->Dr0
= Address
;
734 } else if (Register
== 1) {
735 SystemContext
.SystemContextIa32
->Dr1
= Address
;
739 } else if (Register
== 2) {
740 SystemContext
.SystemContextIa32
->Dr2
= Address
;
744 } else if (Register
== 3) {
745 SystemContext
.SystemContextIa32
->Dr3
= Address
;
750 return EFI_INVALID_PARAMETER
;
753 //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
754 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
760 ‘Z1, [addr], [length]’
761 ‘Z2, [addr], [length]’
762 ‘Z3, [addr], [length]’
763 ‘Z4, [addr], [length]’
765 Insert hardware breakpoint/watchpoint at address addr of size length
767 @param SystemContext Register content at time of the exception
768 @param *PacketData Pointer to the Payload data for the packet
774 IN EFI_SYSTEM_CONTEXT SystemContext
,
783 BREAK_TYPE BreakType
= NotSupported
;
786 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
788 SendError ((UINT8
)ErrorCode
);
794 case 0: //Software breakpoint
795 BreakType
= SoftwareBreakpoint
;
798 case 1: //Hardware breakpoint
799 BreakType
= InstructionExecution
;
802 case 2: //Write watchpoint
803 BreakType
= DataWrite
;
806 case 3: //Read watchpoint
807 BreakType
= DataRead
;
810 case 4: //Access watchpoint
811 BreakType
= DataReadWrite
;
815 Print ((CHAR16
*)L
"Insert breakpoint default: %x\n", Type
);
816 SendError (GDB_EINVALIDBRKPOINTTYPE
);
820 // Find next free debug register
821 Status
= FindNextFreeDebugRegister (SystemContext
, &Register
);
822 if (EFI_ERROR(Status
)) {
823 Print ((CHAR16
*)L
"No space left on device\n");
824 SendError (GDB_ENOSPACE
);
828 // Write Address, length data at particular DR register
829 Status
= EnableDebugRegister (SystemContext
, Register
, Address
, Length
, (UINTN
)BreakType
);
830 if (EFI_ERROR(Status
)) {
832 if (Status
== EFI_UNSUPPORTED
) {
833 Print ((CHAR16
*)L
"Not supported\n");
838 Print ((CHAR16
*)L
"Invalid argument\n");
839 SendError (GDB_EINVALIDARG
);
848 ‘z1, [addr], [length]’
849 ‘z2, [addr], [length]’
850 ‘z3, [addr], [length]’
851 ‘z4, [addr], [length]’
853 Remove hardware breakpoint/watchpoint at address addr of size length
855 @param *PacketData Pointer to the Payload data for the packet
861 IN EFI_SYSTEM_CONTEXT SystemContext
,
869 BREAK_TYPE BreakType
= NotSupported
;
873 //Parse breakpoint packet data
874 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
876 SendError ((UINT8
)ErrorCode
);
882 case 0: //Software breakpoint
883 BreakType
= SoftwareBreakpoint
;
886 case 1: //Hardware breakpoint
887 BreakType
= InstructionExecution
;
890 case 2: //Write watchpoint
891 BreakType
= DataWrite
;
894 case 3: //Read watchpoint
895 BreakType
= DataRead
;
898 case 4: //Access watchpoint
899 BreakType
= DataReadWrite
;
903 SendError (GDB_EINVALIDBRKPOINTTYPE
);
907 //Find matching debug register
908 Status
= FindMatchingDebugRegister (SystemContext
, Address
, Length
, (UINTN
)BreakType
, &Register
);
909 if (EFI_ERROR(Status
)) {
911 if (Status
== EFI_UNSUPPORTED
) {
912 Print ((CHAR16
*)L
"Not supported.\n");
917 Print ((CHAR16
*)L
"No matching register found.\n");
918 SendError (GDB_ENOSPACE
);
923 Status
= DisableDebugRegister(SystemContext
, Register
);
924 if (EFI_ERROR(Status
)) {
925 Print ((CHAR16
*)L
"Invalid argument.\n");
926 SendError (GDB_EINVALIDARG
);
935 InitializeProcessor (
951 IN EFI_EXCEPTION_TYPE ExceptionType
,
952 IN OUT EFI_SYSTEM_CONTEXT SystemContext