2 Processor specific parts of the GDB stub
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <GdbStubInternal.h>
19 // Array of exception types that need to be hooked by the debugger
21 EFI_EXCEPTION_TYPE_ENTRY gExceptionType
[] = {
22 { EXCEPT_X64_DIVIDE_ERROR
, GDB_SIGFPE
},
23 { EXCEPT_X64_DEBUG
, GDB_SIGTRAP
},
24 { EXCEPT_X64_NMI
, GDB_SIGEMT
},
25 { EXCEPT_X64_BREAKPOINT
, GDB_SIGTRAP
},
26 { EXCEPT_X64_OVERFLOW
, GDB_SIGSEGV
},
27 { EXCEPT_X64_BOUND
, GDB_SIGSEGV
},
28 { EXCEPT_X64_INVALID_OPCODE
, GDB_SIGILL
},
29 { EXCEPT_X64_DOUBLE_FAULT
, GDB_SIGEMT
},
30 { EXCEPT_X64_STACK_FAULT
, GDB_SIGSEGV
},
31 { EXCEPT_X64_GP_FAULT
, GDB_SIGSEGV
},
32 { EXCEPT_X64_PAGE_FAULT
, GDB_SIGSEGV
},
33 { EXCEPT_X64_FP_ERROR
, GDB_SIGEMT
},
34 { EXCEPT_X64_ALIGNMENT_CHECK
, GDB_SIGEMT
},
35 { EXCEPT_X64_MACHINE_CHECK
, GDB_SIGEMT
}
39 // The offsets of registers SystemContextX64.
40 // The fields in the array are in the gdb ordering.
41 // HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs
43 UINTN gRegisterOffsets
[] = {
44 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rax
),
45 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rcx
),
46 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rdx
),
47 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rbx
),
48 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rsp
),
49 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rbp
),
50 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rsi
),
51 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rdi
),
52 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rip
),
53 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Rflags
),
54 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Cs
),
55 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Ss
),
56 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Ds
),
57 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Es
),
58 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Fs
),
59 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, Gs
),
60 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R8
),
61 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R9
),
62 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R10
),
63 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R11
),
64 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R12
),
65 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R13
),
66 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R14
),
67 OFFSET_OF(EFI_SYSTEM_CONTEXT_X64
, R15
)
72 Return the number of entries in the gExceptionType[]
74 @retval UINTN, the number of entries in the gExceptionType[] array.
81 return sizeof (gExceptionType
)/sizeof (EFI_EXCEPTION_TYPE_ENTRY
);
86 Return the number of entries in the gRegisters[]
88 @retval UINTN, the number of entries (registers) in the gRegisters[] array.
95 return sizeof (gRegisterOffsets
)/sizeof (UINTN
);
100 Check to see if the ISA is supported.
101 ISA = Instruction Set Architecture
103 @retval TRUE if Isa is supported
107 IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
110 return (BOOLEAN
)(Isa
== IsaX64
);
115 This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
116 It is, by default, set to find the register pointer of the X64 member
117 @param SystemContext Register content at time of the exception
118 @param RegNumber The register to which we want to find a pointer
119 @retval the pointer to the RegNumber-th pointer
122 FindPointerToRegister(
123 IN EFI_SYSTEM_CONTEXT SystemContext
,
128 TempPtr
= ((UINT8
*)SystemContext
.SystemContextX64
) + gRegisterOffsets
[RegNumber
];
129 return (UINTN
*)TempPtr
;
134 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
135 @param SystemContext Register content at time of the exception
136 @param RegNumber the number of the register that we want to read
137 @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
138 @retval the pointer to the next character of the output buffer that is available to be written on.
142 IN EFI_SYSTEM_CONTEXT SystemContext
,
150 while (RegSize
< 64) {
151 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister(SystemContext
, RegNumber
) >> (RegSize
+4)) & 0xf)];
152 *OutBufPtr
++ = mHexToStr
[((*FindPointerToRegister(SystemContext
, RegNumber
) >> RegSize
) & 0xf)];
153 RegSize
= RegSize
+ 8;
160 Reads the n-th register's value into an output buffer and sends it as a packet
161 @param SystemContext Register content at time of the exception
162 @param InBuffer Pointer to the input buffer received from gdb server
166 IN EFI_SYSTEM_CONTEXT SystemContext
,
171 CHAR8 OutBuffer
[17]; // 1 reg=16 hex chars, and the end '\0' (escape seq)
172 CHAR8
*OutBufPtr
; // pointer to the output buffer
174 RegNumber
= AsciiStrHexToUintn (&InBuffer
[1]);
176 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount())) {
177 SendError (GDB_EINVALIDREGNUM
);
181 OutBufPtr
= OutBuffer
;
182 OutBufPtr
= BasicReadRegister(SystemContext
, RegNumber
, OutBufPtr
);
184 *OutBufPtr
= '\0'; // the end of the buffer
185 SendPacket (OutBuffer
);
190 Reads the general registers into an output buffer and sends it as a packet
192 @param SystemContext Register content at time of the exception
196 ReadGeneralRegisters (
197 IN EFI_SYSTEM_CONTEXT SystemContext
201 CHAR8 OutBuffer
[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
202 CHAR8
*OutBufPtr
; // pointer to the output buffer
204 OutBufPtr
= OutBuffer
;
205 for(i
= 0 ; i
< MaxRegisterCount() ; i
++) { // there are only 24 registers to read
206 OutBufPtr
= BasicReadRegister(SystemContext
, i
, OutBufPtr
);
209 *OutBufPtr
= '\0'; // the end of the buffer
210 SendPacket (OutBuffer
);
215 Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
217 @param SystemContext Register content at time of the exception
218 @param RegNumber the number of the register that we want to write
219 @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
220 @retval the pointer to the next character of the input buffer that can be used
224 IN EFI_SYSTEM_CONTEXT SystemContext
,
230 UINTN TempValue
; // the value transferred from a hex char
231 UINT64 NewValue
; // the new value of the RegNumber-th Register
235 while (RegSize
< 64) {
236 TempValue
= HexCharToInt(*InBufPtr
++);
239 SendError (GDB_EBADMEMDATA
);
243 NewValue
+= (TempValue
<< (RegSize
+4));
244 TempValue
= HexCharToInt(*InBufPtr
++);
247 SendError (GDB_EBADMEMDATA
);
251 NewValue
+= (TempValue
<< RegSize
);
252 RegSize
= RegSize
+ 8;
254 *(FindPointerToRegister(SystemContext
, RegNumber
)) = NewValue
;
260 Writes the new value of n-th register received into the input buffer to the n-th register
262 @param SystemContext Register content at time of the exception
263 @param InBuffer Ponter to the input buffer received from gdb server
268 IN EFI_SYSTEM_CONTEXT SystemContext
,
273 CHAR8 RegNumBuffer
[MAX_REG_NUM_BUF_SIZE
]; // put the 'n..' part of the message into this array
275 CHAR8
*InBufPtr
; // pointer to the input buffer
277 // find the register number to write
278 InBufPtr
= &InBuffer
[1];
279 RegNumBufPtr
= RegNumBuffer
;
280 while (*InBufPtr
!= '=') {
281 *RegNumBufPtr
++ = *InBufPtr
++;
283 *RegNumBufPtr
= '\0';
284 RegNumber
= AsciiStrHexToUintn (RegNumBuffer
);
286 // check if this is a valid Register Number
287 if ((RegNumber
< 0) || (RegNumber
>= MaxRegisterCount())) {
288 SendError (GDB_EINVALIDREGNUM
);
291 InBufPtr
++; // skips the '=' character
292 BasicWriteRegister (SystemContext
, RegNumber
, InBufPtr
);
298 Writes the new values received into the input buffer to the general registers
300 @param SystemContext Register content at time of the exception
301 @param InBuffer Pointer to the input buffer received from gdb server
305 WriteGeneralRegisters (
306 IN EFI_SYSTEM_CONTEXT SystemContext
,
311 CHAR8
*InBufPtr
; /// pointer to the input buffer
313 // check to see if the buffer is the right size which is
314 // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385
315 if (AsciiStrLen(InBuffer
) != 385) { // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
316 //Bad message. Message is not the right length
317 SendError (GDB_EBADBUFSIZE
);
321 InBufPtr
= &InBuffer
[1];
323 // Read the new values for the registers from the input buffer to an array, NewValueArray.
324 // The values in the array are in the gdb ordering
325 for(i
=0; i
< MaxRegisterCount(); i
++) { // there are only 16 registers to write
326 InBufPtr
= BasicWriteRegister(SystemContext
, i
, InBufPtr
);
334 Insert Single Step in the SystemContext
336 @param SystemContext Register content at time of the exception
340 IN EFI_SYSTEM_CONTEXT SystemContext
343 SystemContext
.SystemContextX64
->Rflags
|= TF_BIT
; //Setting the TF bit.
349 Remove Single Step in the SystemContext
351 @param SystemContext Register content at time of the exception
355 IN EFI_SYSTEM_CONTEXT SystemContext
358 SystemContext
.SystemContextX64
->Rflags
&= ~TF_BIT
; // clearing the TF bit.
364 Continue. addr is Address to resume. If addr is omitted, resume at current
367 @param SystemContext Register content at time of the exception
372 IN EFI_SYSTEM_CONTEXT SystemContext
,
376 if (PacketData
[1] != '\0') {
377 SystemContext
.SystemContextX64
->Rip
= AsciiStrHexToUintn(&PacketData
[1]);
383 Single step. addr is the Address at which to resume. If addr is omitted, resume
386 @param SystemContext Register content at time of the exception
391 IN EFI_SYSTEM_CONTEXT SystemContext
,
395 if (PacketData
[1] != '\0') {
396 SystemContext
.SystemContextX64
->Rip
= AsciiStrHexToUintn (&PacketData
[1]);
399 AddSingleStep (SystemContext
);
404 Returns breakpoint data address from DR0-DR3 based on the input breakpoint
407 @param SystemContext Register content at time of the exception
408 @param BreakpointNumber Breakpoint number
410 @retval Address Data address from DR0-DR3 based on the
415 GetBreakpointDataAddress (
416 IN EFI_SYSTEM_CONTEXT SystemContext
,
417 IN UINTN BreakpointNumber
422 if (BreakpointNumber
== 1) {
423 Address
= SystemContext
.SystemContextIa32
->Dr0
;
424 } else if (BreakpointNumber
== 2) {
425 Address
= SystemContext
.SystemContextIa32
->Dr1
;
426 } else if (BreakpointNumber
== 3) {
427 Address
= SystemContext
.SystemContextIa32
->Dr2
;
428 } else if (BreakpointNumber
== 4) {
429 Address
= SystemContext
.SystemContextIa32
->Dr3
;
438 Returns currently detected breakpoint value based on the register
440 If no breakpoint is detected then it returns 0.
442 @param SystemContext Register content at time of the exception
444 @retval {1-4} Currently detected breakpoint value
445 @retval 0 No breakpoint detected.
449 GetBreakpointDetected (
450 IN EFI_SYSTEM_CONTEXT SystemContext
454 UINTN BreakpointNumber
;
456 Dr6
.UintN
= SystemContext
.SystemContextIa32
->Dr6
;
458 if (Dr6
.Bits
.B0
== 1) {
459 BreakpointNumber
= 1;
460 } else if (Dr6
.Bits
.B1
== 1) {
461 BreakpointNumber
= 2;
462 } else if (Dr6
.Bits
.B2
== 1) {
463 BreakpointNumber
= 3;
464 } else if (Dr6
.Bits
.B3
== 1) {
465 BreakpointNumber
= 4;
467 BreakpointNumber
= 0; //No breakpoint detected
470 return BreakpointNumber
;
474 Returns Breakpoint type (InstructionExecution, DataWrite, DataRead
475 or DataReadWrite) based on the Breakpoint number
477 @param SystemContext Register content at time of the exception
478 @param BreakpointNumber Breakpoint number
480 @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn
481 field. For unknown value, it returns NotSupported.
486 IN EFI_SYSTEM_CONTEXT SystemContext
,
487 IN UINTN BreakpointNumber
491 BREAK_TYPE Type
= NotSupported
; //Default is NotSupported type
493 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
495 if (BreakpointNumber
== 1) {
496 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW0
;
497 } else if (BreakpointNumber
== 2) {
498 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW1
;
499 } else if (BreakpointNumber
== 3) {
500 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW2
;
501 } else if (BreakpointNumber
== 4) {
502 Type
= (BREAK_TYPE
) Dr7
.Bits
.RW3
;
510 Parses Length and returns the length which DR7 LENn field accepts.
511 For example: If we receive 1-Byte length then we should return 0.
512 Zero gets written to DR7 LENn field.
514 @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
516 @retval Length Appropriate converted values which DR7 LENn field accepts.
524 if (Length
== 1) { //1-Byte length
526 } else if (Length
== 2) { //2-Byte length
528 } else if (Length
== 4) { //4-Byte length
530 } else { //Undefined or 8-byte length
537 Finds the next free debug register. If all the registers are occupied then
538 EFI_OUT_OF_RESOURCES is returned.
540 @param SystemContext Register content at time of the exception
541 @param Register Register value (0 - 3 for the first free debug register)
543 @retval EFI_STATUS Appropriate status value.
547 FindNextFreeDebugRegister (
548 IN EFI_SYSTEM_CONTEXT SystemContext
,
554 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
556 if (Dr7
.Bits
.G0
== 0) {
558 } else if (Dr7
.Bits
.G1
== 0) {
560 } else if (Dr7
.Bits
.G2
== 0) {
562 } else if (Dr7
.Bits
.G3
== 0) {
565 return EFI_OUT_OF_RESOURCES
;
573 Enables the debug register. Writes Address value to appropriate DR0-3 register.
574 Sets LENn, Gn, RWn bits in DR7 register.
576 @param SystemContext Register content at time of the exception
577 @param Register Register value (0 - 3)
578 @param Address Breakpoint address value
579 @param Type Breakpoint type (Instruction, Data write,
580 Data read or write etc.)
582 @retval EFI_STATUS Appropriate status value.
586 EnableDebugRegister (
587 IN EFI_SYSTEM_CONTEXT SystemContext
,
596 //Convert length data
597 Length
= ConvertLengthData (Length
);
599 //For Instruction execution, length should be 0
600 //(Ref. Intel reference manual 18.2.4)
601 if ((Type
== 0) && (Length
!= 0)) {
602 return EFI_INVALID_PARAMETER
;
605 //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
606 //software breakpoint. We should send empty packet in both these cases.
607 if ((Type
== (BREAK_TYPE
)DataRead
) ||
608 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
)) {
609 return EFI_UNSUPPORTED
;
612 //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
613 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
616 SystemContext
.SystemContextIa32
->Dr0
= Address
;
619 Dr7
.Bits
.LEN0
= Length
;
620 } else if (Register
== 1) {
621 SystemContext
.SystemContextIa32
->Dr1
= Address
;
624 Dr7
.Bits
.LEN1
= Length
;
625 } else if (Register
== 2) {
626 SystemContext
.SystemContextIa32
->Dr2
= Address
;
629 Dr7
.Bits
.LEN2
= Length
;
630 } else if (Register
== 3) {
631 SystemContext
.SystemContextIa32
->Dr3
= Address
;
634 Dr7
.Bits
.LEN3
= Length
;
636 return EFI_INVALID_PARAMETER
;
639 //Update Dr7 with appropriate Gn, RWn and LENn bits
640 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
647 Returns register number 0 - 3 for the maching debug register.
648 This function compares incoming Address, Type, Length and
649 if there is a match then it returns the appropriate register number.
650 In case of mismatch, function returns EFI_NOT_FOUND message.
652 @param SystemContext Register content at time of the exception
653 @param Address Breakpoint address value
654 @param Length Breakpoint length value
655 @param Type Breakpoint type (Instruction, Data write, Data read
657 @param Register Register value to be returned
659 @retval EFI_STATUS Appropriate status value.
663 FindMatchingDebugRegister (
664 IN EFI_SYSTEM_CONTEXT SystemContext
,
673 //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
674 //software breakpoint. We should send empty packet in both these cases.
675 if ((Type
== (BREAK_TYPE
)DataRead
) ||
676 (Type
== (BREAK_TYPE
)SoftwareBreakpoint
)) {
677 return EFI_UNSUPPORTED
;
680 //Convert length data
681 Length
= ConvertLengthData(Length
);
683 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
685 if ((Dr7
.Bits
.G0
== 1) &&
686 (Dr7
.Bits
.LEN0
== Length
) &&
687 (Dr7
.Bits
.RW0
== Type
) &&
688 (Address
== SystemContext
.SystemContextIa32
->Dr0
)) {
690 } else if ((Dr7
.Bits
.G1
== 1) &&
691 (Dr7
.Bits
.LEN1
== Length
) &&
692 (Dr7
.Bits
.RW1
== Type
) &&
693 (Address
== SystemContext
.SystemContextIa32
->Dr1
)) {
695 } else if ((Dr7
.Bits
.G2
== 1) &&
696 (Dr7
.Bits
.LEN2
== Length
) &&
697 (Dr7
.Bits
.RW2
== Type
) &&
698 (Address
== SystemContext
.SystemContextIa32
->Dr2
)) {
700 } else if ((Dr7
.Bits
.G3
== 1) &&
701 (Dr7
.Bits
.LEN3
== Length
) &&
702 (Dr7
.Bits
.RW3
== Type
) &&
703 (Address
== SystemContext
.SystemContextIa32
->Dr3
)) {
706 Print ((CHAR16
*)L
"No match found..\n");
707 return EFI_NOT_FOUND
;
715 Disables the particular debug register.
717 @param SystemContext Register content at time of the exception
718 @param Register Register to be disabled
720 @retval EFI_STATUS Appropriate status value.
724 DisableDebugRegister (
725 IN EFI_SYSTEM_CONTEXT SystemContext
,
732 //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
733 Dr7
.UintN
= SystemContext
.SystemContextIa32
->Dr7
;
736 SystemContext
.SystemContextIa32
->Dr0
= Address
;
740 } else if (Register
== 1) {
741 SystemContext
.SystemContextIa32
->Dr1
= Address
;
745 } else if (Register
== 2) {
746 SystemContext
.SystemContextIa32
->Dr2
= Address
;
750 } else if (Register
== 3) {
751 SystemContext
.SystemContextIa32
->Dr3
= Address
;
756 return EFI_INVALID_PARAMETER
;
759 //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
760 SystemContext
.SystemContextIa32
->Dr7
= Dr7
.UintN
;
766 ‘Z1, [addr], [length]’
767 ‘Z2, [addr], [length]’
768 ‘Z3, [addr], [length]’
769 ‘Z4, [addr], [length]’
771 Insert hardware breakpoint/watchpoint at address addr of size length
773 @param SystemContext Register content at time of the exception
774 @param *PacketData Pointer to the Payload data for the packet
780 IN EFI_SYSTEM_CONTEXT SystemContext
,
789 BREAK_TYPE BreakType
= NotSupported
;
792 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
794 SendError ((UINT8
)ErrorCode
);
800 case 0: //Software breakpoint
801 BreakType
= SoftwareBreakpoint
;
804 case 1: //Hardware breakpoint
805 BreakType
= InstructionExecution
;
808 case 2: //Write watchpoint
809 BreakType
= DataWrite
;
812 case 3: //Read watchpoint
813 BreakType
= DataRead
;
816 case 4: //Access watchpoint
817 BreakType
= DataReadWrite
;
821 Print ((CHAR16
*)L
"Insert breakpoint default: %x\n", Type
);
822 SendError (GDB_EINVALIDBRKPOINTTYPE
);
826 // Find next free debug register
827 Status
= FindNextFreeDebugRegister (SystemContext
, &Register
);
828 if (EFI_ERROR(Status
)) {
829 Print ((CHAR16
*)L
"No space left on device\n");
830 SendError (GDB_ENOSPACE
);
834 // Write Address, length data at particular DR register
835 Status
= EnableDebugRegister (SystemContext
, Register
, Address
, Length
, (UINTN
)BreakType
);
836 if (EFI_ERROR(Status
)) {
838 if (Status
== EFI_UNSUPPORTED
) {
839 Print ((CHAR16
*)L
"Not supported\n");
844 Print ((CHAR16
*)L
"Invalid argument\n");
845 SendError (GDB_EINVALIDARG
);
854 ‘z1, [addr], [length]’
855 ‘z2, [addr], [length]’
856 ‘z3, [addr], [length]’
857 ‘z4, [addr], [length]’
859 Remove hardware breakpoint/watchpoint at address addr of size length
861 @param *PacketData Pointer to the Payload data for the packet
867 IN EFI_SYSTEM_CONTEXT SystemContext
,
875 BREAK_TYPE BreakType
= NotSupported
;
879 //Parse breakpoint packet data
880 ErrorCode
= ParseBreakpointPacket (PacketData
, &Type
, &Address
, &Length
);
882 SendError ((UINT8
)ErrorCode
);
888 case 0: //Software breakpoint
889 BreakType
= SoftwareBreakpoint
;
892 case 1: //Hardware breakpoint
893 BreakType
= InstructionExecution
;
896 case 2: //Write watchpoint
897 BreakType
= DataWrite
;
900 case 3: //Read watchpoint
901 BreakType
= DataRead
;
904 case 4: //Access watchpoint
905 BreakType
= DataReadWrite
;
909 SendError (GDB_EINVALIDBRKPOINTTYPE
);
913 //Find matching debug register
914 Status
= FindMatchingDebugRegister (SystemContext
, Address
, Length
, (UINTN
)BreakType
, &Register
);
915 if (EFI_ERROR(Status
)) {
917 if (Status
== EFI_UNSUPPORTED
) {
918 Print ((CHAR16
*)L
"Not supported.\n");
923 Print ((CHAR16
*)L
"No matching register found.\n");
924 SendError (GDB_ENOSPACE
);
929 Status
= DisableDebugRegister(SystemContext
, Register
);
930 if (EFI_ERROR(Status
)) {
931 Print ((CHAR16
*)L
"Invalid argument.\n");
932 SendError (GDB_EINVALIDARG
);
941 InitializeProcessor (
957 IN EFI_EXCEPTION_TYPE ExceptionType
,
958 IN OUT EFI_SYSTEM_CONTEXT SystemContext