-}
-
-
-/**
- Returns breakpoint data address from DR0-DR3 based on the input breakpoint number
-
- @param SystemContext Register content at time of the exception
- @param BreakpointNumber Breakpoint number
-
- @retval Address Data address from DR0-DR3 based on the breakpoint number.
-
-**/
-UINTN
-GetBreakpointDataAddress (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN BreakpointNumber
- )
-{
- UINTN Address;
-
- if (BreakpointNumber == 1) {
- Address = SystemContext.SystemContextIa32->Dr0;
- } else if (BreakpointNumber == 2) {
- Address = SystemContext.SystemContextIa32->Dr1;
- } else if (BreakpointNumber == 3) {
- Address = SystemContext.SystemContextIa32->Dr2;
- } else if (BreakpointNumber == 4) {
- Address = SystemContext.SystemContextIa32->Dr3;
- } else {
- Address = 0;
- }
-
- return Address;
-}
-
-
-/**
- Returns currently detected breakpoint value based on the register DR6 B0-B3 field.
- If no breakpoint is detected then it returns 0.
-
- @param SystemContext Register content at time of the exception
-
- @retval {1-4} Currently detected breakpoint value
- @retval 0 No breakpoint detected.
-
-**/
-UINTN
-GetBreakpointDetected (
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
-{
- IA32_DR6 Dr6;
- UINTN BreakpointNumber;
-
- Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
-
- if (Dr6.Bits.B0 == 1) {
- BreakpointNumber = 1;
- } else if (Dr6.Bits.B1 == 1) {
- BreakpointNumber = 2;
- } else if (Dr6.Bits.B2 == 1) {
- BreakpointNumber = 3;
- } else if (Dr6.Bits.B3 == 1) {
- BreakpointNumber = 4;
- } else {
- BreakpointNumber = 0; //No breakpoint detected
- }
-
- return BreakpointNumber;
-}
-
-
-/**
- Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite)
- based on the Breakpoint number
-
- @param SystemContext Register content at time of the exception
- @param BreakpointNumber Breakpoint number
-
- @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field
- For unknown value, it returns NotSupported.
-
-**/
-BREAK_TYPE
-GetBreakpointType (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN BreakpointNumber
- )
-{
- IA32_DR7 Dr7;
- BREAK_TYPE Type = NotSupported; //Default is NotSupported type
-
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
-
- if (BreakpointNumber == 1) {
- Type = (BREAK_TYPE) Dr7.Bits.RW0;
- } else if (BreakpointNumber == 2) {
- Type = (BREAK_TYPE) Dr7.Bits.RW1;
- } else if (BreakpointNumber == 3) {
- Type = (BREAK_TYPE) Dr7.Bits.RW2;
- } else if (BreakpointNumber == 4) {
- Type = (BREAK_TYPE) Dr7.Bits.RW3;
- }
-
- return Type;
-}
-
-
-/**
- Parses Length and returns the length which DR7 LENn field accepts.
- For example: If we receive 1-Byte length then we should return 0.
- Zero gets written to DR7 LENn field.
-
- @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
-
- @retval Length Appropriate converted values which DR7 LENn field accepts.
-
-**/
-UINTN
-ConvertLengthData (
- IN UINTN Length
- )
-{
- if (Length == 1) { //1-Byte length
- return 0;
- } else if (Length == 2) { //2-Byte length
- return 1;
- } else if (Length == 4) { //4-Byte length
- return 3;
- } else { //Undefined or 8-byte length
- return 2;
- }
-}
-
-
-/**
- Finds the next free debug register. If all the registers are occupied then
- EFI_OUT_OF_RESOURCES is returned.
-
- @param SystemContext Register content at time of the exception
- @param Register Register value (0 - 3 for the first free debug register)
-
- @retval EFI_STATUS Appropriate status value.
-
-**/
-EFI_STATUS
-FindNextFreeDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- OUT UINTN *Register
- )
-{
- IA32_DR7 Dr7;
-
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
-
- if (Dr7.Bits.G0 == 0) {
- *Register = 0;
- } else if (Dr7.Bits.G1 == 0) {
- *Register = 1;
- } else if (Dr7.Bits.G2 == 0) {
- *Register = 2;
- } else if (Dr7.Bits.G3 == 0) {
- *Register = 3;
- } else {
- return EFI_OUT_OF_RESOURCES;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Enables the debug register. Writes Address value to appropriate DR0-3 register.
- Sets LENn, Gn, RWn bits in DR7 register.
-
- @param SystemContext Register content at time of the exception
- @param Register Register value (0 - 3)
- @param Address Breakpoint address value
- @param Type Breakpoint type (Instruction, Data write, Data read
- or write etc.)
-
- @retval EFI_STATUS Appropriate status value.
-
-**/
-EFI_STATUS
-EnableDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN Register,
- IN UINTN Address,
- IN UINTN Length,
- IN UINTN Type
- )
-{
- IA32_DR7 Dr7;
-
- //Convert length data
- Length = ConvertLengthData (Length);
-
- //For Instruction execution, length should be 0
- //(Ref. Intel reference manual 18.2.4)
- if ((Type == 0) && (Length != 0)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
- //software breakpoint. We should send empty packet in both these cases.
- if ((Type == (BREAK_TYPE)DataRead) ||
- (Type == (BREAK_TYPE)SoftwareBreakpoint)) {
- return EFI_UNSUPPORTED;
- }
-
- //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
-
- if (Register == 0) {
- SystemContext.SystemContextIa32->Dr0 = Address;
- Dr7.Bits.G0 = 1;
- Dr7.Bits.RW0 = Type;
- Dr7.Bits.LEN0 = Length;
- } else if (Register == 1) {
- SystemContext.SystemContextIa32->Dr1 = Address;
- Dr7.Bits.G1 = 1;
- Dr7.Bits.RW1 = Type;
- Dr7.Bits.LEN1 = Length;
- } else if (Register == 2) {
- SystemContext.SystemContextIa32->Dr2 = Address;
- Dr7.Bits.G2 = 1;
- Dr7.Bits.RW2 = Type;
- Dr7.Bits.LEN2 = Length;
- } else if (Register == 3) {
- SystemContext.SystemContextIa32->Dr3 = Address;
- Dr7.Bits.G3 = 1;
- Dr7.Bits.RW3 = Type;
- Dr7.Bits.LEN3 = Length;
- } else {
- return EFI_INVALID_PARAMETER;
- }
-
- //Update Dr7 with appropriate Gn, RWn and LENn bits
- SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Returns register number 0 - 3 for the maching debug register.
- This function compares incoming Address, Type, Length and
- if there is a match then it returns the appropriate register number.
- In case of mismatch, function returns EFI_NOT_FOUND message.
-
- @param SystemContext Register content at time of the exception
- @param Address Breakpoint address value
- @param Length Breakpoint length value
- @param Type Breakpoint type (Instruction, Data write,
- Data read or write etc.)
- @param Register Register value to be returned
-
- @retval EFI_STATUS Appropriate status value.
-
-**/
-EFI_STATUS
-FindMatchingDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN Address,
- IN UINTN Length,
- IN UINTN Type,
- OUT UINTN *Register
- )
-{
- IA32_DR7 Dr7;
-
- //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
- //software breakpoint. We should send empty packet in both these cases.
- if ((Type == (BREAK_TYPE)DataRead) ||
- (Type == (BREAK_TYPE)SoftwareBreakpoint)) {
- return EFI_UNSUPPORTED;
- }
-
- //Convert length data
- Length = ConvertLengthData(Length);
-
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
-
- if ((Dr7.Bits.G0 == 1) &&
- (Dr7.Bits.LEN0 == Length) &&
- (Dr7.Bits.RW0 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr0)) {
- *Register = 0;
- } else if ((Dr7.Bits.G1 == 1) &&
- (Dr7.Bits.LEN1 == Length) &&
- (Dr7.Bits.RW1 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr1)) {
- *Register = 1;
- } else if ((Dr7.Bits.G2 == 1) &&
- (Dr7.Bits.LEN2 == Length) &&
- (Dr7.Bits.RW2 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr2)) {
- *Register = 2;
- } else if ((Dr7.Bits.G3 == 1) &&
- (Dr7.Bits.LEN3 == Length) &&
- (Dr7.Bits.RW3 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr3)) {
- *Register = 3;
- } else {
- Print ((CHAR16 *)L"No match found..\n");
- return EFI_NOT_FOUND;
- }
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Disables the particular debug register.
-
- @param SystemContext Register content at time of the exception
- @param Register Register to be disabled
-
- @retval EFI_STATUS Appropriate status value.
-
-**/
-EFI_STATUS
-DisableDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN Register
- )
-{
- IA32_DR7 Dr7;
- UINTN Address = 0;
-
- //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
-
- if (Register == 0) {
- SystemContext.SystemContextIa32->Dr0 = Address;
- Dr7.Bits.G0 = 0;
- Dr7.Bits.RW0 = 0;
- Dr7.Bits.LEN0 = 0;
- } else if (Register == 1) {
- SystemContext.SystemContextIa32->Dr1 = Address;
- Dr7.Bits.G1 = 0;
- Dr7.Bits.RW1 = 0;
- Dr7.Bits.LEN1 = 0;
- } else if (Register == 2) {
- SystemContext.SystemContextIa32->Dr2 = Address;
- Dr7.Bits.G2 = 0;
- Dr7.Bits.RW2 = 0;
- Dr7.Bits.LEN2 = 0;
- } else if (Register == 3) {
- SystemContext.SystemContextIa32->Dr3 = Address;
- Dr7.Bits.G3 = 0;
- Dr7.Bits.RW3 = 0;
- Dr7.Bits.LEN3 = 0;
- } else {
- return EFI_INVALID_PARAMETER;
- }
-
- //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
- SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- ‘Z1, [addr], [length]’
- ‘Z2, [addr], [length]’
- ‘Z3, [addr], [length]’
- ‘Z4, [addr], [length]’
-
- Insert hardware breakpoint/watchpoint at address addr of size length
-
- @param SystemContext Register content at time of the exception
- @param *PacketData Pointer to the Payload data for the packet
-
-**/
-VOID
-EFIAPI
-InsertBreakPoint (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *PacketData
- )
-{
- UINTN Type;
- UINTN Address;
- UINTN Length;
- UINTN Register;
- EFI_STATUS Status;
- BREAK_TYPE BreakType = NotSupported;
- UINTN ErrorCode;
-
- ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
- if (ErrorCode > 0) {
- SendError ((UINT8)ErrorCode);
- return;
- }
-
- switch (Type) {
-
- case 0: //Software breakpoint
- BreakType = SoftwareBreakpoint;
- break;
-
- case 1: //Hardware breakpoint
- BreakType = InstructionExecution;
- break;
-
- case 2: //Write watchpoint
- BreakType = DataWrite;
- break;
-
- case 3: //Read watchpoint
- BreakType = DataRead;
- break;
-
- case 4: //Access watchpoint
- BreakType = DataReadWrite;
- break;
-
- default :
- Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
- SendError (GDB_EINVALIDBRKPOINTTYPE);
- return;
- }
-
- // Find next free debug register
- Status = FindNextFreeDebugRegister (SystemContext, &Register);
- if (EFI_ERROR(Status)) {
- Print ((CHAR16 *)L"No space left on device\n");
- SendError (GDB_ENOSPACE);
- return;
- }
-
- // Write Address, length data at particular DR register
- Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
- if (EFI_ERROR(Status)) {
- if (Status == EFI_UNSUPPORTED) {
- SendNotSupported();
- return;
- }
-
- SendError (GDB_EINVALIDARG);
- return;
- }
-
- SendSuccess ();
-}
-
-
-/**
- ‘z1, [addr], [length]’
- ‘z2, [addr], [length]’
- ‘z3, [addr], [length]’
- ‘z4, [addr], [length]’
-
- Remove hardware breakpoint/watchpoint at address addr of size length
-
- @param *PacketData Pointer to the Payload data for the packet
-
-**/
-VOID
-EFIAPI
-RemoveBreakPoint (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *PacketData
- )
-{
- UINTN Type;
- UINTN Address;
- UINTN Length;
- UINTN Register;
- BREAK_TYPE BreakType = NotSupported;
- EFI_STATUS Status;
- UINTN ErrorCode;
-
- //Parse breakpoint packet data
- ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
- if (ErrorCode > 0) {
- SendError ((UINT8)ErrorCode);
- return;
- }
-
- switch (Type) {
-
- case 0: //Software breakpoint
- BreakType = SoftwareBreakpoint;
- break;
-
- case 1: //Hardware breakpoint
- BreakType = InstructionExecution;
- break;
-
- case 2: //Write watchpoint
- BreakType = DataWrite;
- break;
-
- case 3: //Read watchpoint
- BreakType = DataRead;
- break;
-
- case 4: //Access watchpoint
- BreakType = DataReadWrite;
- break;
-
- default :
- SendError (GDB_EINVALIDBRKPOINTTYPE);
- return;
- }
-
- //Find matching debug register
- Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
- if (EFI_ERROR(Status)) {
- if (Status == EFI_UNSUPPORTED) {
- SendNotSupported();
- return;
- }
-
- SendError (GDB_ENOSPACE);
- return;
- }
-
- //Remove breakpoint
- Status = DisableDebugRegister(SystemContext, Register);
- if (EFI_ERROR(Status)) {
- SendError (GDB_EINVALIDARG);
- return;
- }
-
- SendSuccess ();
-}
-
-
+}\r
+\r
+\r
+/**\r
+ Returns breakpoint data address from DR0-DR3 based on the input breakpoint number\r
+\r
+ @param SystemContext Register content at time of the exception\r
+ @param BreakpointNumber Breakpoint number\r
+\r
+ @retval Address Data address from DR0-DR3 based on the breakpoint number.\r
+\r
+**/\r
+UINTN\r
+GetBreakpointDataAddress (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN UINTN BreakpointNumber\r
+ )\r
+{\r
+ UINTN Address;\r
+\r
+ if (BreakpointNumber == 1) {\r
+ Address = SystemContext.SystemContextIa32->Dr0;\r
+ } else if (BreakpointNumber == 2) {\r
+ Address = SystemContext.SystemContextIa32->Dr1;\r
+ } else if (BreakpointNumber == 3) {\r
+ Address = SystemContext.SystemContextIa32->Dr2;\r
+ } else if (BreakpointNumber == 4) {\r
+ Address = SystemContext.SystemContextIa32->Dr3;\r
+ } else {\r
+ Address = 0;\r
+ }\r
+\r
+ return Address;\r
+}\r
+\r
+\r
+/**\r
+ Returns currently detected breakpoint value based on the register DR6 B0-B3 field.\r
+ If no breakpoint is detected then it returns 0.\r
+\r
+ @param SystemContext Register content at time of the exception\r
+\r
+ @retval {1-4} Currently detected breakpoint value\r
+ @retval 0 No breakpoint detected.\r
+\r
+**/\r
+UINTN\r
+GetBreakpointDetected (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ IA32_DR6 Dr6;\r
+ UINTN BreakpointNumber;\r
+\r
+ Dr6.UintN = SystemContext.SystemContextIa32->Dr6;\r
+\r
+ if (Dr6.Bits.B0 == 1) {\r
+ BreakpointNumber = 1;\r
+ } else if (Dr6.Bits.B1 == 1) {\r
+ BreakpointNumber = 2;\r
+ } else if (Dr6.Bits.B2 == 1) {\r
+ BreakpointNumber = 3;\r
+ } else if (Dr6.Bits.B3 == 1) {\r
+ BreakpointNumber = 4;\r
+ } else {\r
+ BreakpointNumber = 0; //No breakpoint detected\r
+ }\r
+\r
+ return BreakpointNumber;\r
+}\r
+\r
+\r
+/**\r
+ Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite)\r
+ based on the Breakpoint number\r
+\r
+ @param SystemContext Register content at time of the exception\r
+ @param BreakpointNumber Breakpoint number\r
+\r
+ @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field\r
+ For unknown value, it returns NotSupported.\r
+\r
+**/\r
+BREAK_TYPE\r
+GetBreakpointType (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN UINTN BreakpointNumber\r
+ )\r
+{\r
+ IA32_DR7 Dr7;\r
+ BREAK_TYPE Type = NotSupported; //Default is NotSupported type\r
+\r
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;\r
+\r
+ if (BreakpointNumber == 1) {\r
+ Type = (BREAK_TYPE) Dr7.Bits.RW0;\r
+ } else if (BreakpointNumber == 2) {\r
+ Type = (BREAK_TYPE) Dr7.Bits.RW1;\r
+ } else if (BreakpointNumber == 3) {\r
+ Type = (BREAK_TYPE) Dr7.Bits.RW2;\r
+ } else if (BreakpointNumber == 4) {\r
+ Type = (BREAK_TYPE) Dr7.Bits.RW3;\r
+ }\r
+\r
+ return Type;\r
+}\r
+\r
+\r
+/**\r
+ Parses Length and returns the length which DR7 LENn field accepts.\r
+ For example: If we receive 1-Byte length then we should return 0.\r
+ Zero gets written to DR7 LENn field.\r
+\r
+ @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)\r
+\r
+ @retval Length Appropriate converted values which DR7 LENn field accepts.\r
+\r
+**/\r
+UINTN\r
+ConvertLengthData (\r
+ IN UINTN Length\r
+ )\r
+{\r
+ if (Length == 1) { //1-Byte length\r
+ return 0;\r
+ } else if (Length == 2) { //2-Byte length\r
+ return 1;\r
+ } else if (Length == 4) { //4-Byte length\r
+ return 3;\r
+ } else { //Undefined or 8-byte length\r
+ return 2;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Finds the next free debug register. If all the registers are occupied then\r
+ EFI_OUT_OF_RESOURCES is returned.\r
+\r
+ @param SystemContext Register content at time of the exception\r
+ @param Register Register value (0 - 3 for the first free debug register)\r
+\r
+ @retval EFI_STATUS Appropriate status value.\r
+\r
+**/\r
+EFI_STATUS\r
+FindNextFreeDebugRegister (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ OUT UINTN *Register\r
+ )\r
+{\r
+ IA32_DR7 Dr7;\r
+\r
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;\r
+\r
+ if (Dr7.Bits.G0 == 0) {\r
+ *Register = 0;\r
+ } else if (Dr7.Bits.G1 == 0) {\r
+ *Register = 1;\r
+ } else if (Dr7.Bits.G2 == 0) {\r
+ *Register = 2;\r
+ } else if (Dr7.Bits.G3 == 0) {\r
+ *Register = 3;\r
+ } else {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Enables the debug register. Writes Address value to appropriate DR0-3 register.\r
+ Sets LENn, Gn, RWn bits in DR7 register.\r
+\r
+ @param SystemContext Register content at time of the exception\r
+ @param Register Register value (0 - 3)\r
+ @param Address Breakpoint address value\r
+ @param Type Breakpoint type (Instruction, Data write, Data read\r
+ or write etc.)\r
+\r
+ @retval EFI_STATUS Appropriate status value.\r
+\r
+**/\r
+EFI_STATUS\r
+EnableDebugRegister (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN UINTN Register,\r
+ IN UINTN Address,\r
+ IN UINTN Length,\r
+ IN UINTN Type\r
+ )\r
+{\r
+ IA32_DR7 Dr7;\r
+\r
+ //Convert length data\r
+ Length = ConvertLengthData (Length);\r
+\r
+ //For Instruction execution, length should be 0\r
+ //(Ref. Intel reference manual 18.2.4)\r
+ if ((Type == 0) && (Length != 0)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle\r
+ //software breakpoint. We should send empty packet in both these cases.\r
+ if ((Type == (BREAK_TYPE)DataRead) ||\r
+ (Type == (BREAK_TYPE)SoftwareBreakpoint)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.\r
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;\r
+\r
+ if (Register == 0) {\r
+ SystemContext.SystemContextIa32->Dr0 = Address;\r
+ Dr7.Bits.G0 = 1;\r
+ Dr7.Bits.RW0 = Type;\r
+ Dr7.Bits.LEN0 = Length;\r
+ } else if (Register == 1) {\r
+ SystemContext.SystemContextIa32->Dr1 = Address;\r
+ Dr7.Bits.G1 = 1;\r
+ Dr7.Bits.RW1 = Type;\r
+ Dr7.Bits.LEN1 = Length;\r
+ } else if (Register == 2) {\r
+ SystemContext.SystemContextIa32->Dr2 = Address;\r
+ Dr7.Bits.G2 = 1;\r
+ Dr7.Bits.RW2 = Type;\r
+ Dr7.Bits.LEN2 = Length;\r
+ } else if (Register == 3) {\r
+ SystemContext.SystemContextIa32->Dr3 = Address;\r
+ Dr7.Bits.G3 = 1;\r
+ Dr7.Bits.RW3 = Type;\r
+ Dr7.Bits.LEN3 = Length;\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //Update Dr7 with appropriate Gn, RWn and LENn bits\r
+ SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Returns register number 0 - 3 for the maching debug register.\r
+ This function compares incoming Address, Type, Length and\r
+ if there is a match then it returns the appropriate register number.\r
+ In case of mismatch, function returns EFI_NOT_FOUND message.\r
+\r
+ @param SystemContext Register content at time of the exception\r
+ @param Address Breakpoint address value\r
+ @param Length Breakpoint length value\r
+ @param Type Breakpoint type (Instruction, Data write,\r
+ Data read or write etc.)\r
+ @param Register Register value to be returned\r
+\r
+ @retval EFI_STATUS Appropriate status value.\r
+\r
+**/\r
+EFI_STATUS\r
+FindMatchingDebugRegister (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN UINTN Address,\r
+ IN UINTN Length,\r
+ IN UINTN Type,\r
+ OUT UINTN *Register\r
+ )\r
+{\r
+ IA32_DR7 Dr7;\r
+\r
+ //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle\r
+ //software breakpoint. We should send empty packet in both these cases.\r
+ if ((Type == (BREAK_TYPE)DataRead) ||\r
+ (Type == (BREAK_TYPE)SoftwareBreakpoint)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //Convert length data\r
+ Length = ConvertLengthData(Length);\r
+\r
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;\r
+\r
+ if ((Dr7.Bits.G0 == 1) &&\r
+ (Dr7.Bits.LEN0 == Length) &&\r
+ (Dr7.Bits.RW0 == Type) &&\r
+ (Address == SystemContext.SystemContextIa32->Dr0)) {\r
+ *Register = 0;\r
+ } else if ((Dr7.Bits.G1 == 1) &&\r
+ (Dr7.Bits.LEN1 == Length) &&\r
+ (Dr7.Bits.RW1 == Type) &&\r
+ (Address == SystemContext.SystemContextIa32->Dr1)) {\r
+ *Register = 1;\r
+ } else if ((Dr7.Bits.G2 == 1) &&\r
+ (Dr7.Bits.LEN2 == Length) &&\r
+ (Dr7.Bits.RW2 == Type) &&\r
+ (Address == SystemContext.SystemContextIa32->Dr2)) {\r
+ *Register = 2;\r
+ } else if ((Dr7.Bits.G3 == 1) &&\r
+ (Dr7.Bits.LEN3 == Length) &&\r
+ (Dr7.Bits.RW3 == Type) &&\r
+ (Address == SystemContext.SystemContextIa32->Dr3)) {\r
+ *Register = 3;\r
+ } else {\r
+ Print ((CHAR16 *)L"No match found..\n");\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Disables the particular debug register.\r
+\r
+ @param SystemContext Register content at time of the exception\r
+ @param Register Register to be disabled\r
+\r
+ @retval EFI_STATUS Appropriate status value.\r
+\r
+**/\r
+EFI_STATUS\r
+DisableDebugRegister (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN UINTN Register\r
+ )\r
+{\r
+ IA32_DR7 Dr7;\r
+ UINTN Address = 0;\r
+\r
+ //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.\r
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;\r
+\r
+ if (Register == 0) {\r
+ SystemContext.SystemContextIa32->Dr0 = Address;\r
+ Dr7.Bits.G0 = 0;\r
+ Dr7.Bits.RW0 = 0;\r
+ Dr7.Bits.LEN0 = 0;\r
+ } else if (Register == 1) {\r
+ SystemContext.SystemContextIa32->Dr1 = Address;\r
+ Dr7.Bits.G1 = 0;\r
+ Dr7.Bits.RW1 = 0;\r
+ Dr7.Bits.LEN1 = 0;\r
+ } else if (Register == 2) {\r
+ SystemContext.SystemContextIa32->Dr2 = Address;\r
+ Dr7.Bits.G2 = 0;\r
+ Dr7.Bits.RW2 = 0;\r
+ Dr7.Bits.LEN2 = 0;\r
+ } else if (Register == 3) {\r
+ SystemContext.SystemContextIa32->Dr3 = Address;\r
+ Dr7.Bits.G3 = 0;\r
+ Dr7.Bits.RW3 = 0;\r
+ Dr7.Bits.LEN3 = 0;\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.\r
+ SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ ‘Z1, [addr], [length]’\r
+ ‘Z2, [addr], [length]’\r
+ ‘Z3, [addr], [length]’\r
+ ‘Z4, [addr], [length]’\r
+\r
+ Insert hardware breakpoint/watchpoint at address addr of size length\r
+\r
+ @param SystemContext Register content at time of the exception\r
+ @param *PacketData Pointer to the Payload data for the packet\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InsertBreakPoint (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN CHAR8 *PacketData\r
+ )\r
+{\r
+ UINTN Type;\r
+ UINTN Address;\r
+ UINTN Length;\r
+ UINTN Register;\r
+ EFI_STATUS Status;\r
+ BREAK_TYPE BreakType = NotSupported;\r
+ UINTN ErrorCode;\r
+\r
+ ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);\r
+ if (ErrorCode > 0) {\r
+ SendError ((UINT8)ErrorCode);\r
+ return;\r
+ }\r
+\r
+ switch (Type) {\r
+\r
+ case 0: //Software breakpoint\r
+ BreakType = SoftwareBreakpoint;\r
+ break;\r
+\r
+ case 1: //Hardware breakpoint\r
+ BreakType = InstructionExecution;\r
+ break;\r
+\r
+ case 2: //Write watchpoint\r
+ BreakType = DataWrite;\r
+ break;\r
+\r
+ case 3: //Read watchpoint\r
+ BreakType = DataRead;\r
+ break;\r
+\r
+ case 4: //Access watchpoint\r
+ BreakType = DataReadWrite;\r
+ break;\r
+\r
+ default :\r
+ Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);\r
+ SendError (GDB_EINVALIDBRKPOINTTYPE);\r
+ return;\r
+ }\r
+\r
+ // Find next free debug register\r
+ Status = FindNextFreeDebugRegister (SystemContext, &Register);\r
+ if (EFI_ERROR(Status)) {\r
+ Print ((CHAR16 *)L"No space left on device\n");\r
+ SendError (GDB_ENOSPACE);\r
+ return;\r
+ }\r
+\r
+ // Write Address, length data at particular DR register\r
+ Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);\r
+ if (EFI_ERROR(Status)) {\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ SendNotSupported();\r
+ return;\r
+ }\r
+\r
+ SendError (GDB_EINVALIDARG);\r
+ return;\r
+ }\r
+\r
+ SendSuccess ();\r
+}\r
+\r
+\r
+/**\r
+ ‘z1, [addr], [length]’\r
+ ‘z2, [addr], [length]’\r
+ ‘z3, [addr], [length]’\r
+ ‘z4, [addr], [length]’\r
+\r
+ Remove hardware breakpoint/watchpoint at address addr of size length\r
+\r
+ @param *PacketData Pointer to the Payload data for the packet\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RemoveBreakPoint (\r
+ IN EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN CHAR8 *PacketData\r
+ )\r
+{\r
+ UINTN Type;\r
+ UINTN Address;\r
+ UINTN Length;\r
+ UINTN Register;\r
+ BREAK_TYPE BreakType = NotSupported;\r
+ EFI_STATUS Status;\r
+ UINTN ErrorCode;\r
+\r
+ //Parse breakpoint packet data\r
+ ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);\r
+ if (ErrorCode > 0) {\r
+ SendError ((UINT8)ErrorCode);\r
+ return;\r
+ }\r
+\r
+ switch (Type) {\r
+\r
+ case 0: //Software breakpoint\r
+ BreakType = SoftwareBreakpoint;\r
+ break;\r
+\r
+ case 1: //Hardware breakpoint\r
+ BreakType = InstructionExecution;\r
+ break;\r
+\r
+ case 2: //Write watchpoint\r
+ BreakType = DataWrite;\r
+ break;\r
+\r
+ case 3: //Read watchpoint\r
+ BreakType = DataRead;\r
+ break;\r
+\r
+ case 4: //Access watchpoint\r
+ BreakType = DataReadWrite;\r
+ break;\r
+\r
+ default :\r
+ SendError (GDB_EINVALIDBRKPOINTTYPE);\r
+ return;\r
+ }\r
+\r
+ //Find matching debug register\r
+ Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);\r
+ if (EFI_ERROR(Status)) {\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ SendNotSupported();\r
+ return;\r
+ }\r
+\r
+ SendError (GDB_ENOSPACE);\r
+ return;\r
+ }\r
+\r
+ //Remove breakpoint\r
+ Status = DisableDebugRegister(SystemContext, Register);\r
+ if (EFI_ERROR(Status)) {\r
+ SendError (GDB_EINVALIDARG);\r
+ return;\r
+ }\r
+\r
+ SendSuccess ();\r
+}\r
+\r
+\r