# 1/123 faster than Stm or Vstm version\r
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf\r
\r
- # Uncomment to turn on GDB stub in SEC.\r
- #DebugAgentLib|EmbeddedPkg/Library/GdbDebugAgent/GdbDebugAgent.inf\r
-\r
[LibraryClasses.common.PEI_CORE]\r
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
ReportStatusCodeLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf\r
EmbeddedPkg/Library/AcpiLib/AcpiLib.inf\r
EmbeddedPkg/Library/DebugAgentTimerLibNull/DebugAgentTimerLibNull.inf\r
EmbeddedPkg/Library/FdtLib/FdtLib.inf\r
- EmbeddedPkg/Library/GdbDebugAgent/GdbDebugAgent.inf\r
EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf\r
EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf\r
\r
+++ /dev/null
-#------------------------------------------------------------------------------\r
-#\r
-# Use ARMv6 instruction to operate on a single stack\r
-#\r
-# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
-#\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#------------------------------------------------------------------------------\r
-\r
-/*\r
-\r
-This is the stack constructed by the exception handler (low address to high address)\r
- # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
- Reg Offset\r
- === ======\r
- R0 0x00 # stmfd SP!,{R0-R12}\r
- R1 0x04\r
- R2 0x08\r
- R3 0x0c\r
- R4 0x10\r
- R5 0x14\r
- R6 0x18\r
- R7 0x1c\r
- R8 0x20\r
- R9 0x24\r
- R10 0x28\r
- R11 0x2c\r
- R12 0x30\r
- SP 0x34 # reserved via adding 0x20 (32) to the SP\r
- LR 0x38\r
- PC 0x3c\r
- CPSR 0x40\r
- DFSR 0x44\r
- DFAR 0x48\r
- IFSR 0x4c\r
- IFAR 0x50\r
-\r
- LR 0x54 # SVC Link register (we need to restore it)\r
-\r
- LR 0x58 # pushed by srsfd\r
- CPSR 0x5c\r
-\r
- */\r
-\r
-\r
-GCC_ASM_EXPORT(ExceptionHandlersStart)\r
-GCC_ASM_EXPORT(ExceptionHandlersEnd)\r
-GCC_ASM_EXPORT(CommonExceptionEntry)\r
-GCC_ASM_EXPORT(AsmCommonExceptionEntry)\r
-GCC_ASM_EXPORT(GdbExceptionHandler)\r
-\r
-.text\r
-.align 3\r
-\r
-\r
-//\r
-// This code gets copied to the ARM vector table\r
-// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
-//\r
-ASM_PFX(ExceptionHandlersStart):\r
-\r
-ASM_PFX(Reset):\r
- b ASM_PFX(Reset)\r
-\r
-ASM_PFX(UndefinedInstruction):\r
- b ASM_PFX(UndefinedInstructionEntry)\r
-\r
-ASM_PFX(SoftwareInterrupt):\r
- b ASM_PFX(SoftwareInterruptEntry)\r
-\r
-ASM_PFX(PrefetchAbort):\r
- b ASM_PFX(PrefetchAbortEntry)\r
-\r
-ASM_PFX(DataAbort):\r
- b ASM_PFX(DataAbortEntry)\r
-\r
-ASM_PFX(ReservedException):\r
- b ASM_PFX(ReservedExceptionEntry)\r
-\r
-ASM_PFX(Irq):\r
- b ASM_PFX(Irq)\r
-\r
-ASM_PFX(Fiq):\r
- b ASM_PFX(FiqEntry)\r
-\r
-\r
-ASM_PFX(UndefinedInstructionEntry):\r
- sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cpsid f,#0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#1 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(SoftwareInterruptEntry):\r
- sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cpsid f @ We are already in SVC mode\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#2 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(PrefetchAbortEntry):\r
- sub LR,LR,#4\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cpsid f,#0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#3 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(DataAbortEntry):\r
- sub LR,LR,#8\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cpsid f,#0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#4\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(ReservedExceptionEntry):\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cpsid f,#0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#5\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(FiqEntry):\r
- sub LR,LR,#4\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cps #0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
- @ Since we have already switch to SVC R8_fiq - R12_fiq\r
- @ never get used or saved\r
- mov R0,#7 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-//\r
-// This gets patched by the C code that patches in the vector table\r
-//\r
-ASM_PFX(CommonExceptionEntry):\r
- .byte 0x12\r
- .byte 0x34\r
- .byte 0x56\r
- .byte 0x78\r
-\r
-ASM_PFX(ExceptionHandlersEnd):\r
-\r
-//\r
-// This code runs from CpuDxe driver loaded address. It is patched into\r
-// CommonExceptionEntry.\r
-//\r
-ASM_PFX(AsmCommonExceptionEntry):\r
- mrc p15, 0, R1, c6, c0, 2 @ Read IFAR\r
- str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 1 @ Read IFSR\r
- str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
-\r
- mrc p15, 0, R1, c6, c0, 0 @ Read DFAR\r
- str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 0 @ Read DFSR\r
- str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
-\r
- ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack\r
- str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
-\r
- add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R3, R1, #0x1f @ Check CPSR to see if User or System Mode\r
- cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1df))\r
- cmpne R3, #0x10 @\r
- stmeqed R2, {lr}^ @ save unbanked lr\r
- @ else\r
- stmneed R2, {lr} @ save SVC lr\r
-\r
-\r
- ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd\r
- @ Check to see if we have to adjust for Thumb entry\r
- sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType ==2)) {\r
- cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb\r
- bhi NoAdjustNeeded\r
-\r
- tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry\r
- addne R5, R5, #2 @ PC += 2@\r
- str R5,[SP,#0x58] @ Update LR value pused by srsfd\r
-\r
-NoAdjustNeeded:\r
-\r
- str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
-\r
- sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack\r
- str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
-\r
- @ R0 is ExceptionType\r
- mov R1,SP @ R1 is SystemContext\r
-\r
-/*\r
-VOID\r
-EFIAPI\r
-GdbExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
- )\r
-\r
-*/\r
- blx ASM_PFX(GdbExceptionHandler) @ Call exception handler\r
-\r
- ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC\r
- str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored\r
-\r
- ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR\r
- str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored\r
-\r
- add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry\r
- add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R1, R1, #0x1f @ Check to see if User or System Mode\r
- cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))\r
- cmpne R1, #0x10 @\r
- ldmeqed R2, {lr}^ @ restore unbanked lr\r
- @ else\r
- ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}\r
-\r
- ldmfd SP!,{R0-R12} @ Restore general purpose registers\r
- @ Exception handler can not change SP\r
-\r
- add SP,SP,#0x20 @ Clear out the remaining stack space\r
- ldmfd SP!,{LR} @ restore the link register for this context\r
- rfefd SP! @ return from exception via srsfd stack slot\r
-\r
+++ /dev/null
-//------------------------------------------------------------------------------\r
-//\r
-// Use ARMv6 instruction to operate on a single stack\r
-//\r
-// Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
-//\r
-// This program and the accompanying materials\r
-// are licensed and made available under the terms and conditions of the BSD License\r
-// which accompanies this distribution. The full text of the license may be found at\r
-// http://opensource.org/licenses/bsd-license.php\r
-//\r
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-//\r
-//------------------------------------------------------------------------------\r
-\r
-\r
-\r
-/*\r
-\r
-This is the stack constructed by the exception handler (low address to high address)\r
- # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
- Reg Offset\r
- === ======\r
- R0 0x00 # stmfd SP!,{R0-R12}\r
- R1 0x04\r
- R2 0x08\r
- R3 0x0c\r
- R4 0x10\r
- R5 0x14\r
- R6 0x18\r
- R7 0x1c\r
- R8 0x20\r
- R9 0x24\r
- R10 0x28\r
- R11 0x2c\r
- R12 0x30\r
- SP 0x34 # reserved via adding 0x20 (32) to the SP\r
- LR 0x38\r
- PC 0x3c\r
- CPSR 0x40\r
- DFSR 0x44\r
- DFAR 0x48\r
- IFSR 0x4c\r
- IFAR 0x50\r
-\r
- LR 0x54 # SVC Link register (we need to restore it)\r
-\r
- LR 0x58 # pushed by srsfd\r
- CPSR 0x5c\r
-\r
- */\r
-\r
-\r
- EXPORT ExceptionHandlersStart\r
- EXPORT ExceptionHandlersEnd\r
- EXPORT CommonExceptionEntry\r
- EXPORT AsmCommonExceptionEntry\r
- IMPORT GdbExceptionHandler\r
-\r
- PRESERVE8\r
- AREA DxeExceptionHandlers, CODE, READONLY\r
-\r
-//\r
-// This code gets copied to the ARM vector table\r
-// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
-//\r
-ExceptionHandlersStart\r
-\r
-Reset\r
- b Reset\r
-\r
-UndefinedInstruction\r
- b UndefinedInstructionEntry\r
-\r
-SoftwareInterrupt\r
- b SoftwareInterruptEntry\r
-\r
-PrefetchAbort\r
- b PrefetchAbortEntry\r
-\r
-DataAbort\r
- b DataAbortEntry\r
-\r
-ReservedException\r
- b ReservedExceptionEntry\r
-\r
-Irq\r
- b Irq\r
-\r
-Fiq\r
- b FiqEntry\r
-\r
-\r
-UndefinedInstructionEntry\r
- sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cpsid f, #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#1 ; ExceptionType\r
- ldr R1,CommonExceptionEntry;\r
- bx R1\r
-\r
-SoftwareInterruptEntry\r
- sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cpsid f ; We are already in SVC mode\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#2 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-PrefetchAbortEntry\r
- sub LR,LR,#4\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cpsid f, #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#3 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-DataAbortEntry\r
- sub LR,LR,#8\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cpsid f, #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#4 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-ReservedExceptionEntry\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cpsid f, #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#5 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-FiqEntry\r
- sub LR,LR,#4\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cps #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
- ; Since we have already switch to SVC R8_fiq - R12_fiq\r
- ; never get used or saved\r
- mov R0,#7 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-//\r
-// This gets patched by the C code that patches in the vector table\r
-//\r
-CommonExceptionEntry\r
- dcd 0x12345678\r
-\r
-ExceptionHandlersEnd\r
-\r
-//\r
-// This code runs from CpuDxe driver loaded address. It is patched into\r
-// CommonExceptionEntry.\r
-//\r
-AsmCommonExceptionEntry\r
- mrc p15, 0, R1, c6, c0, 2 ; Read IFAR\r
- str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 1 ; Read IFSR\r
- str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
-\r
- mrc p15, 0, R1, c6, c0, 0 ; Read DFAR\r
- str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 0 ; Read DFSR\r
- str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
-\r
- ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack\r
- str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
-\r
- add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R3, R1, #0x1f ; Check CPSR to see if User or System Mode\r
- cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df))\r
- cmpne R3, #0x10 ;\r
- stmeqed R2, {lr}^ ; save unbanked lr\r
- ; else\r
- stmneed R2, {lr} ; save SVC lr\r
-\r
-\r
- ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd\r
- ; Check to see if we have to adjust for Thumb entry\r
- sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType ==2)) {\r
- cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb\r
- bhi NoAdjustNeeded\r
-\r
- tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry\r
- addne R5, R5, #2 ; PC += 2;\r
- str R5,[SP,#0x58] ; Update LR value pused by srsfd\r
-\r
-NoAdjustNeeded\r
-\r
- str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
-\r
- sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack\r
- str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
-\r
- ; R0 is ExceptionType\r
- mov R1,SP ; R1 is SystemContext\r
-\r
-/*\r
-VOID\r
-EFIAPI\r
-GdbExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
- )\r
-\r
-*/\r
- blx GdbExceptionHandler ; Call exception handler\r
-\r
- ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC\r
- str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored\r
-\r
- ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR\r
- str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored\r
-\r
- add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry\r
- add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R1, R1, #0x1f ; Check to see if User or System Mode\r
- cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))\r
- cmpne R1, #0x10 ;\r
- ldmeqed R2, {lr}^ ; restore unbanked lr\r
- ; else\r
- ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR}\r
-\r
- ldmfd SP!,{R0-R12} ; Restore general purpose registers\r
- ; Exception handler can not change SP\r
-\r
- add SP,SP,#0x20 ; Clear out the remaining stack space\r
- ldmfd SP!,{LR} ; restore the link register for this context\r
- rfefd SP! ; return from exception via srsfd stack slot\r
-\r
- END\r
-\r
-\r
+++ /dev/null
-/** @file\r
- Processor specific parts of the GDB stub\r
-\r
- Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
-\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-\r
-#include <GdbDebugAgent.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/ArmLib.h>\r
-\r
-//\r
-// Externs from the exception handler assembly file\r
-//\r
-VOID\r
-ExceptionHandlersStart (\r
- VOID\r
- );\r
-\r
-VOID\r
-ExceptionHandlersEnd (\r
- VOID\r
- );\r
-\r
-VOID\r
-CommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-VOID\r
-AsmCommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-\r
-//\r
-// Array of exception types that need to be hooked by the debugger\r
-// (efi, gdb) //efi number\r
-//\r
-EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {\r
- { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP },\r
- { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },\r
- { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP },\r
- { EXCEPT_ARM_DATA_ABORT, GDB_SIGTRAP }, // GDB_SIGEMT\r
- { EXCEPT_ARM_RESERVED, GDB_SIGTRAP }, // GDB_SIGILL\r
- { EXCEPT_ARM_FIQ, GDB_SIGINT } // Used for ctrl-c\r
-};\r
-\r
-// Shut up some annoying RVCT warnings\r
-#ifdef __CC_ARM\r
-#pragma diag_suppress 1296\r
-#endif\r
-\r
-UINTN gRegisterOffsets[] = {\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC),\r
- 0x00000F01, // f0\r
- 0x00000F02,\r
- 0x00000F03,\r
- 0x00000F11, // f1\r
- 0x00000F12,\r
- 0x00000F13,\r
- 0x00000F21, // f2\r
- 0x00000F22,\r
- 0x00000F23,\r
- 0x00000F31, // f3\r
- 0x00000F32,\r
- 0x00000F33,\r
- 0x00000F41, // f4\r
- 0x00000F42,\r
- 0x00000F43,\r
- 0x00000F51, // f5\r
- 0x00000F52,\r
- 0x00000F53,\r
- 0x00000F61, // f6\r
- 0x00000F62,\r
- 0x00000F63,\r
- 0x00000F71, // f7\r
- 0x00000F72,\r
- 0x00000F73,\r
- 0x00000FFF, // fps\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR)\r
-};\r
-\r
-// restore warnings for RVCT\r
-#ifdef __CC_ARM\r
-#pragma diag_default 1296\r
-#endif\r
-\r
-\r
-/**\r
- Return the number of entries in the gExceptionType[]\r
-\r
- @retval UINTN, the number of entries in the gExceptionType[] array.\r
- **/\r
-UINTN\r
-MaxEfiException (\r
- VOID\r
- )\r
-{\r
- return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);\r
-}\r
-\r
-\r
-\r
-\r
-/**\r
- Check to see if the ISA is supported.\r
- ISA = Instruction Set Architecture\r
-\r
- @retval TRUE if Isa is supported\r
-\r
-**/\r
-BOOLEAN\r
-CheckIsa (\r
- IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa\r
- )\r
-{\r
- if (Isa == IsaArm) {\r
- return TRUE;\r
- } else {\r
- return FALSE;\r
- }\r
-}\r
-\r
-\r
-/**\r
- This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering\r
- It is, by default, set to find the register pointer of the ARM member\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber The register to which we want to find a pointer\r
- @retval the pointer to the RegNumber-th pointer\r
- **/\r
-UINTN *\r
-FindPointerToRegister(\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber\r
- )\r
-{\r
- UINT8 *TempPtr;\r
- ASSERT(gRegisterOffsets[RegNumber] < 0xF00);\r
- TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];\r
- return (UINT32 *)TempPtr;\r
-}\r
-\r
-\r
-/**\r
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber the number of the register that we want to read\r
- @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.\r
- @retval the pointer to the next character of the output buffer that is available to be written on.\r
- **/\r
-CHAR8 *\r
-BasicReadRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *OutBufPtr\r
- )\r
-{\r
- UINTN RegSize;\r
- CHAR8 Char;\r
-\r
- if (gRegisterOffsets[RegNumber] > 0xF00) {\r
- AsciiSPrint(OutBufPtr, 9, "00000000");\r
- OutBufPtr += 8;\r
- return OutBufPtr;\r
- }\r
-\r
- RegSize = 0;\r
- while (RegSize < 32) {\r
- Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];\r
- if ((Char >= 'A') && (Char <= 'F')) {\r
- Char = Char - 'A' + 'a';\r
- }\r
- *OutBufPtr++ = Char;\r
-\r
- Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];\r
- if ((Char >= 'A') && (Char <= 'F')) {\r
- Char = Char - 'A' + 'a';\r
- }\r
- *OutBufPtr++ = Char;\r
-\r
- RegSize = RegSize + 8;\r
- }\r
- return OutBufPtr;\r
-}\r
-\r
-\r
-/**\r
- Reads the n-th register's value into an output buffer and sends it as a packet\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Pointer to the input buffer received from gdb server\r
- **/\r
-VOID\r
-ReadNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN RegNumber;\r
- CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)\r
- CHAR8 *OutBufPtr; // pointer to the output buffer\r
-\r
- RegNumber = AsciiStrHexToUintn (&InBuffer[1]);\r
-\r
- if (RegNumber >= (sizeof (gRegisterOffsets)/sizeof (UINTN))) {\r
- SendError (GDB_EINVALIDREGNUM);\r
- return;\r
- }\r
-\r
- OutBufPtr = OutBuffer;\r
- OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);\r
-\r
- *OutBufPtr = '\0'; // the end of the buffer\r
- SendPacket(OutBuffer);\r
-}\r
-\r
-\r
-/**\r
- Reads the general registers into an output buffer and sends it as a packet\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-ReadGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- UINTN Index;\r
- // a UINT32 takes 8 ascii characters\r
- CHAR8 OutBuffer[(sizeof (gRegisterOffsets) * 2) + 1];\r
- CHAR8 *OutBufPtr;\r
-\r
- // It is not safe to allocate pool here....\r
- OutBufPtr = OutBuffer;\r
- for (Index = 0; Index < (sizeof (gRegisterOffsets)/sizeof (UINTN)); Index++) {\r
- OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);\r
- }\r
-\r
- *OutBufPtr = '\0';\r
- SendPacket(OutBuffer);\r
-}\r
-\r
-\r
-/**\r
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber the number of the register that we want to write\r
- @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.\r
- @retval the pointer to the next character of the input buffer that can be used\r
- **/\r
-CHAR8 *\r
-BasicWriteRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *InBufPtr\r
- )\r
-{\r
- UINTN RegSize;\r
- UINTN TempValue; // the value transferred from a hex char\r
- UINT32 NewValue; // the new value of the RegNumber-th Register\r
-\r
- if (gRegisterOffsets[RegNumber] > 0xF00) {\r
- return InBufPtr + 8;\r
- }\r
-\r
- NewValue = 0;\r
- RegSize = 0;\r
- while (RegSize < 32) {\r
- TempValue = HexCharToInt(*InBufPtr++);\r
-\r
- if ((INTN)TempValue < 0) {\r
- SendError (GDB_EBADMEMDATA);\r
- return NULL;\r
- }\r
-\r
- NewValue += (TempValue << (RegSize+4));\r
- TempValue = HexCharToInt(*InBufPtr++);\r
-\r
- if ((INTN)TempValue < 0) {\r
- SendError (GDB_EBADMEMDATA);\r
- return NULL;\r
- }\r
-\r
- NewValue += (TempValue << RegSize);\r
- RegSize = RegSize + 8;\r
- }\r
- *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;\r
- return InBufPtr;\r
-}\r
-\r
-\r
-/** ‘P n...=r...’\r
- Writes the new value of n-th register received into the input buffer to the n-th register\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Ponter to the input buffer received from gdb server\r
- **/\r
-VOID\r
-WriteNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN RegNumber;\r
- CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array\r
- CHAR8 *RegNumBufPtr;\r
- CHAR8 *InBufPtr; // pointer to the input buffer\r
-\r
- // find the register number to write\r
- InBufPtr = &InBuffer[1];\r
- RegNumBufPtr = RegNumBuffer;\r
- while (*InBufPtr != '=') {\r
- *RegNumBufPtr++ = *InBufPtr++;\r
- }\r
- *RegNumBufPtr = '\0';\r
- RegNumber = AsciiStrHexToUintn (RegNumBuffer);\r
-\r
- // check if this is a valid Register Number\r
- if (RegNumber >= (sizeof (gRegisterOffsets)/sizeof (UINTN))) {\r
- SendError (GDB_EINVALIDREGNUM);\r
- return;\r
- }\r
- InBufPtr++; // skips the '=' character\r
- BasicWriteRegister (SystemContext, RegNumber, InBufPtr);\r
- SendSuccess();\r
-}\r
-\r
-\r
-/** ‘G XX...’\r
- Writes the new values received into the input buffer to the general registers\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Pointer to the input buffer received from gdb server\r
- **/\r
-\r
-VOID\r
-EFIAPI\r
-WriteGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN i;\r
- CHAR8 *InBufPtr; /// pointer to the input buffer\r
- UINTN MinLength;\r
- UINTN RegisterCount = (sizeof (gRegisterOffsets)/sizeof (UINTN));\r
-\r
- MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format\r
-\r
- if (AsciiStrLen(InBuffer) < MinLength) {\r
- //Bad message. Message is not the right length\r
- SendError (GDB_EBADBUFSIZE);\r
- return;\r
- }\r
-\r
- InBufPtr = &InBuffer[1];\r
-\r
- // Read the new values for the registers from the input buffer to an array, NewValueArray.\r
- // The values in the array are in the gdb ordering\r
- for(i = 0; i < RegisterCount; i++) {\r
- InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);\r
- }\r
-\r
- SendSuccess ();\r
-}\r
-\r
-\r
-\r
-\r
-/**\r
- Continue. addr is Address to resume. If addr is omitted, resume at current\r
- Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-ContinueAtAddress (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- if (PacketData[1] != '\0') {\r
- SystemContext.SystemContextArm->PC = AsciiStrHexToUintn(&PacketData[1]);\r
- }\r
-}\r
-\r
-\r
-/** ‘s [addr ]’\r
- Single step. addr is the Address at which to resume. If addr is omitted, resume\r
- at same Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-SingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- SendNotSupported();\r
-}\r
-\r
-\r
-VOID\r
-EFIAPI\r
-InsertBreakPoint (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- SendNotSupported ();\r
-}\r
-\r
-VOID\r
-EFIAPI\r
-RemoveBreakPoint (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- SendNotSupported ();\r
-}\r
-\r
-\r
-/**\r
- Send the T signal with the given exception type (in gdb order) and possibly\r
- with n:r pairs related to the watchpoints\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param GdbExceptionType GDB exception type\r
- **/\r
-VOID\r
-ProcessorSendTSignal (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINT8 GdbExceptionType,\r
- IN OUT CHAR8 *TSignalPtr,\r
- IN UINTN SizeOfBuffer\r
- )\r
-{\r
- *TSignalPtr = '\0';\r
-}\r
-\r
-/**\r
- FIQ state is only changed by FIQ exception. We don't want to take FIQ\r
- ticks in the GDB stub. The stub disables FIQ on entry, but this is the\r
- third instruction that executes in the execption handler. Thus we have\r
- a crack we need to test for.\r
-\r
- @param PC PC of execption\r
-\r
- @return TRUE We are in the GDB stub exception preamble\r
- @return FALSE We are not in GDB stub code\r
- **/\r
-BOOLEAN\r
-InFiqCrack (\r
- IN UINT32 PC\r
- )\r
-{\r
- UINT64 VectorBase = PcdGet64 (PcdCpuVectorBaseAddress);\r
- UINT32 Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
-\r
- if ((PC >= VectorBase) && (PC <= (VectorBase + Length))) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-/**\r
- Check to see if this exception is related to ctrl-c handling.\r
-\r
- In this scheme we dedicate FIQ to the ctrl-c handler so it is\r
- independent of the rest of the system.\r
-\r
- SaveAndSetDebugTimerInterrupt () can be used to\r
-\r
- @param ExceptionType Exception that is being processed\r
- @param SystemContext Register content at time of the exception\r
-\r
- @return TRUE This was a ctrl-c check that did not find a ctrl-c\r
- @return FALSE This was not a ctrl-c check or some one hit ctrl-c\r
- **/\r
-BOOLEAN\r
-ProcessorControlC (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- CHAR8 Char;\r
- BOOLEAN Return = TRUE;\r
-\r
- if (ExceptionType != EXCEPT_ARM_FIQ) {\r
- // Skip it as it is not related to ctrl-c\r
- return FALSE;\r
- }\r
-\r
- if (InFiqCrack (SystemContext.SystemContextArm->PC)) {\r
- // We are in our own interrupt preable, so skip this tick.\r
- // We never want to let gdb see the debug stub running if we can help it\r
- return FALSE;\r
- }\r
-\r
- while (TRUE) {\r
- if (!GdbIsCharAvailable ()) {\r
- //\r
- // No characters are pending so exit the loop\r
- //\r
- Return = TRUE;\r
- break;\r
- }\r
-\r
- Char = GdbGetChar ();\r
- if (Char == 0x03) {\r
- //\r
- // We have a ctrl-c so exit and process exception for ctrl-c\r
- //\r
- Return = FALSE;\r
- break;\r
- }\r
- }\r
-\r
- DebugAgentTimerEndOfInterrupt ();\r
-\r
- // Force an exit from the exception handler as we are done\r
- return Return;\r
-}\r
-\r
-\r
-/**\r
- Enable/Disable the interrupt of debug timer and return the interrupt state\r
- prior to the operation.\r
-\r
- If EnableStatus is TRUE, enable the interrupt of debug timer.\r
- If EnableStatus is FALSE, disable the interrupt of debug timer.\r
-\r
- @param[in] EnableStatus Enable/Disable.\r
-\r
- @retval TRUE Debug timer interrupt were enabled on entry to this call.\r
- @retval FALSE Debug timer interrupt were disabled on entry to this call.\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-SaveAndSetDebugTimerInterrupt (\r
- IN BOOLEAN EnableStatus\r
- )\r
-{\r
- BOOLEAN FiqEnabled;\r
-\r
- FiqEnabled = ArmGetFiqState ();\r
-\r
- if (EnableStatus) {\r
- DebugAgentTimerSetPeriod (PcdGet32 (PcdGdbTimerPeriodMilliseconds));\r
- ArmEnableFiq ();\r
- } else {\r
- DebugAgentTimerSetPeriod (0);\r
- ArmDisableFiq ();\r
- }\r
-\r
- return FiqEnabled;\r
-}\r
-\r
-\r
-\r
-VOID\r
-GdbFPutString (\r
- IN CHAR8 *String\r
- );\r
-\r
-/**\r
- Initialize debug agent.\r
-\r
- This function is used to set up debug environment to support source level debugging.\r
- If certain Debug Agent Library instance has to save some private data in the stack,\r
- this function must work on the mode that doesn't return to the caller, then\r
- the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one\r
- function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is\r
- responsible to invoke the passing-in function at the end of InitializeDebugAgent().\r
-\r
- If the parameter Function is not NULL, Debug Agent Library instance will invoke it by\r
- passing in the Context to be its parameter.\r
-\r
- If Function() is NULL, Debug Agent Library instance will return after setup debug\r
- environment.\r
-\r
- @param[in] InitFlag Init flag is used to decide the initialize process.\r
- @param[in] Context Context needed according to InitFlag; it was optional.\r
- @param[in] Function Continue function called by debug agent library; it was\r
- optional.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-InitializeDebugAgent (\r
- IN UINT32 InitFlag,\r
- IN VOID *Context, OPTIONAL\r
- IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
- )\r
-{\r
- UINTN Offset;\r
- UINTN Length;\r
- BOOLEAN IrqEnabled;\r
- UINT64 *VectorBase;\r
-\r
-\r
- //\r
- // Disable interrupts\r
- //\r
- IrqEnabled = ArmGetInterruptState ();\r
- ArmDisableInterrupts ();\r
- ArmDisableFiq ();\r
-\r
- //\r
- // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.\r
- //\r
- Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
-\r
- //\r
- // Reserve space for the exception handlers\r
- //\r
- VectorBase = (UINT64 *)(UINTN)PcdGet64 (PcdCpuVectorBaseAddress);\r
-\r
-\r
- // Copy our assembly code into the page that contains the exception vectors.\r
- CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
-\r
- //\r
- // Patch in the common Assembly exception handler\r
- //\r
- Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;\r
- *(UINTN *) (((UINT8 *)VectorBase) + Offset) = (UINTN)AsmCommonExceptionEntry;\r
-\r
- // Flush Caches since we updated executable stuff\r
- InvalidateInstructionCacheRange ((VOID *)(UINTN)PcdGet64(PcdCpuVectorBaseAddress), Length);\r
-\r
- // setup a timer so gdb can break in via ctrl-c\r
- DebugAgentTimerIntialize ();\r
-\r
- if (IrqEnabled) {\r
- ArmEnableInterrupts ();\r
- }\r
-\r
- if (Function != NULL) {\r
- Function (Context);\r
- }\r
-\r
- return;\r
-}\r
-\r
+++ /dev/null
-/** @file\r
- Debug Agent library implementition with empty functions.\r
-\r
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "GdbDebugAgent.h"\r
-\r
-\r
-UINTN gMaxProcessorIndex = 0;\r
-\r
-//\r
-// Buffers for basic gdb communication\r
-//\r
-CHAR8 gInBuffer[MAX_BUF_SIZE];\r
-CHAR8 gOutBuffer[MAX_BUF_SIZE];\r
-\r
-\r
-//\r
-// Globals for returning XML from qXfer:libraries:read packet\r
-//\r
-UINTN gPacketqXferLibraryOffset = 0;\r
-UINTN gEfiDebugImageTableEntry = 0;\r
-CHAR8 gXferLibraryBuffer[2000];\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
-\r
-\r
-// add-symbol-file c:/work/edk2/Build/BeagleBoard/DEBUG_GCC48/ARM/BeagleBoardPkg/Sec/Sec/DEBUG/BeagleBoardSec.dll 0x80008360\r
-CHAR8 *qXferHack = "<library name=\"c:/work/edk2/Build/BeagleBoard/DEBUG_GCC48/ARM/BeagleBoardPkg/Sec/Sec/DEBUG/BeagleBoardSec.dll\"><segment address=\"0x80008360\"/></library>";\r
-\r
-UINTN\r
-gXferObjectReadResponse (\r
- IN CHAR8 Type,\r
- IN CHAR8 *Str\r
- )\r
-{\r
- CHAR8 *OutBufPtr; // pointer to the output buffer\r
- CHAR8 Char;\r
- UINTN Count;\r
-\r
- // responce starts with 'm' or 'l' if it is the end\r
- OutBufPtr = gOutBuffer;\r
- *OutBufPtr++ = Type;\r
- Count = 1;\r
-\r
- // Binary data encoding\r
- OutBufPtr = gOutBuffer;\r
- while (*Str != '\0') {\r
- Char = *Str++;\r
- if ((Char == 0x7d) || (Char == 0x23) || (Char == 0x24) || (Char == 0x2a)) {\r
- // escape character\r
- *OutBufPtr++ = 0x7d;\r
-\r
- Char ^= 0x20;\r
- }\r
- *OutBufPtr++ = Char;\r
- Count++;\r
- }\r
-\r
- *OutBufPtr = '\0' ; // the end of the buffer\r
- SendPacket (gOutBuffer);\r
-\r
- return Count;\r
-}\r
-\r
-/**\r
- Process "qXfer:object:read:annex:offset,length" request.\r
-\r
- Returns an XML document that contains loaded libraries. In our case it is\r
- infomration in the EFI Debug Inmage Table converted into an XML document.\r
-\r
- GDB will call with an arbitrary length (it can't know the real length and\r
- will reply with chunks of XML that are easy for us to deal with. Gdb will\r
- keep calling until we say we are done. XML doc looks like:\r
-\r
- <library-list>\r
- <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library>\r
- <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library>\r
- <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library>\r
- </library-list>\r
-\r
- Since we can not allocate memory in interupt context this module has\r
- assumptions about how it will get called:\r
- 1) Length will generally be max remote packet size (big enough)\r
- 2) First Offset of an XML document read needs to be 0\r
- 3) This code will return back small chunks of the XML document on every read.\r
- Each subseqent call will ask for the next available part of the document.\r
-\r
- Note: The only variable size element in the XML is:\r
- " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is\r
- based on the file path and name of the symbol file. If the symbol file name\r
- is bigger than the max gdb remote packet size we could update this code\r
- to respond back in chunks.\r
-\r
- @param Offset offset into special data area\r
- @param Length number of bytes to read starting at Offset\r
-\r
- **/\r
-VOID\r
-QxferLibrary (\r
- IN UINTN Offset,\r
- IN UINTN Length\r
- )\r
-{\r
- gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', "<library-list>\n");\r
- gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', qXferHack);\r
- gXferObjectReadResponse ('l', "</library-list>\n");\r
- gPacketqXferLibraryOffset = 0;\r
-}\r
-\r
-/**\r
- Transfer length bytes of input buffer, starting at Address, to memory.\r
-\r
- @param length the number of the bytes to be transferred/written\r
- @param *address the start address of the transferring/writing the memory\r
- @param *new_data the new data to be written to memory\r
- **/\r
-\r
-VOID\r
-TransferFromInBufToMem (\r
- IN UINTN Length,\r
- IN unsigned char *Address,\r
- IN CHAR8 *NewData\r
- )\r
-{\r
- CHAR8 c1;\r
- CHAR8 c2;\r
-\r
- while (Length-- > 0) {\r
- c1 = (CHAR8)HexCharToInt (*NewData++);\r
- c2 = (CHAR8)HexCharToInt (*NewData++);\r
-\r
- if ((c1 < 0) || (c2 < 0)) {\r
- SendError (GDB_EBADMEMDATA);\r
- return;\r
- }\r
- *Address++ = (UINT8)((c1 << 4) + c2);\r
- }\r
-\r
- SendSuccess();\r
-}\r
-\r
-\r
-/**\r
- Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer\r
- as a packet.\r
-\r
- @param Length the number of the bytes to be transferred/read\r
- @param *address pointer to the start address of the transferring/reading the memory\r
- **/\r
-\r
-VOID\r
-TransferFromMemToOutBufAndSend (\r
- IN UINTN Length,\r
- IN unsigned char *Address\r
- )\r
-{\r
- // there are Length bytes and every byte is represented as 2 hex chars\r
- CHAR8 OutBuffer[MAX_BUF_SIZE];\r
- CHAR8 *OutBufPtr; // pointer to the output buffer\r
- CHAR8 Char;\r
-\r
- OutBufPtr = OutBuffer;\r
- while (Length > 0) {\r
-\r
- Char = mHexToStr[*Address >> 4];\r
- if ((Char >= 'A') && (Char <= 'F')) {\r
- Char = Char - 'A' + 'a';\r
- }\r
- *OutBufPtr++ = Char;\r
-\r
- Char = mHexToStr[*Address & 0x0f];\r
- if ((Char >= 'A') && (Char <= 'F')) {\r
- Char = Char - 'A' + 'a';\r
- }\r
- *OutBufPtr++ = Char;\r
-\r
- Address++;\r
- Length--;\r
- }\r
-\r
- *OutBufPtr = '\0' ; // the end of the buffer\r
- SendPacket (OutBuffer);\r
-}\r
-\r
-\r
-\r
-/**\r
- Send a GDB Remote Serial Protocol Packet\r
-\r
- $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',\r
- the packet teminating character '#' and the two digit checksum.\r
-\r
- If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up\r
- in an infinit loop. This is so if you unplug the debugger code just keeps running\r
-\r
- @param PacketData Payload data for the packet\r
-\r
-\r
- @retval Number of bytes of packet data sent.\r
-\r
-**/\r
-UINTN\r
-SendPacket (\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- UINT8 CheckSum;\r
- UINTN Timeout;\r
- CHAR8 *Ptr;\r
- CHAR8 TestChar;\r
- UINTN Count;\r
-\r
- Timeout = PcdGet32 (PcdGdbMaxPacketRetryCount);\r
-\r
- Count = 0;\r
- do {\r
-\r
- Ptr = PacketData;\r
-\r
- if (Timeout-- == 0) {\r
- // Only try a finite number of times so we don't get stuck in the loop\r
- return Count;\r
- }\r
-\r
- // Packet prefix\r
- GdbPutChar ('$');\r
-\r
- for (CheckSum = 0, Count =0 ; *Ptr != '\0'; Ptr++, Count++) {\r
- GdbPutChar (*Ptr);\r
- CheckSum = CheckSum + *Ptr;\r
- }\r
-\r
- // Packet terminating character and checksum\r
- GdbPutChar ('#');\r
- GdbPutChar (mHexToStr[CheckSum >> 4]);\r
- GdbPutChar (mHexToStr[CheckSum & 0x0F]);\r
-\r
- TestChar = GdbGetChar ();\r
- } while (TestChar != '+');\r
-\r
- return Count;\r
-}\r
-\r
-/**\r
- Receive a GDB Remote Serial Protocol Packet\r
-\r
- $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',\r
- the packet teminating character '#' and the two digit checksum.\r
-\r
- If host re-starts sending a packet without ending the previous packet, only the last valid packet is processed.\r
- (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)\r
-\r
- If an ack '+' is not sent resend the packet\r
-\r
- @param PacketData Payload data for the packet\r
-\r
- @retval Number of bytes of packet data received.\r
-\r
-**/\r
-UINTN\r
-ReceivePacket (\r
- OUT CHAR8 *PacketData,\r
- IN UINTN PacketDataSize\r
- )\r
-{\r
- UINT8 CheckSum;\r
- UINTN Index;\r
- CHAR8 Char;\r
- CHAR8 SumString[3];\r
- CHAR8 TestChar;\r
-\r
- ZeroMem (PacketData, PacketDataSize);\r
-\r
- for (;;) {\r
- // wait for the start of a packet\r
- TestChar = GdbGetChar ();\r
- while (TestChar != '$') {\r
- TestChar = GdbGetChar ();\r
- };\r
-\r
- retry:\r
- for (Index = 0, CheckSum = 0; Index < (PacketDataSize - 1); Index++) {\r
- Char = GdbGetChar ();\r
- if (Char == '$') {\r
- goto retry;\r
- }\r
- if (Char == '#') {\r
- break;\r
- }\r
-\r
- PacketData[Index] = Char;\r
- CheckSum = CheckSum + Char;\r
- }\r
- PacketData[Index] = '\0';\r
-\r
- if (Index == PacketDataSize) {\r
- continue;\r
- }\r
-\r
- SumString[0] = GdbGetChar ();\r
- SumString[1] = GdbGetChar ();\r
- SumString[2] = '\0';\r
-\r
- if (AsciiStrHexToUintn (SumString) == CheckSum) {\r
- // Ack: Success\r
- GdbPutChar ('+');\r
-\r
- // Null terminate the callers string\r
- PacketData[Index] = '\0';\r
- return Index;\r
- } else {\r
- // Ack: Failure\r
- GdbPutChar ('-');\r
- }\r
- }\r
-\r
- //return 0;\r
-}\r
-\r
-\r
-/**\r
- Empties the given buffer\r
- @param Buf pointer to the first element in buffer to be emptied\r
- **/\r
-VOID\r
-EmptyBuffer (\r
- IN CHAR8 *Buf\r
- )\r
-{\r
- *Buf = '\0';\r
-}\r
-\r
-\r
-/**\r
- Converts an 8-bit Hex Char into a INTN.\r
-\r
- @param Char the hex character to be converted into UINTN\r
- @retval a INTN, from 0 to 15, that corressponds to Char\r
- -1 if Char is not a hex character\r
- **/\r
-INTN\r
-HexCharToInt (\r
- IN CHAR8 Char\r
- )\r
-{\r
- if ((Char >= 'A') && (Char <= 'F')) {\r
- return Char - 'A' + 10;\r
- } else if ((Char >= 'a') && (Char <= 'f')) {\r
- return Char - 'a' + 10;\r
- } else if ((Char >= '0') && (Char <= '9')) {\r
- return Char - '0';\r
- } else { // if not a hex value, return a negative value\r
- return -1;\r
- }\r
-}\r
-\r
- // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end\r
-CHAR8 *gError = "E__";\r
-\r
-/** 'E NN'\r
- Send an error with the given error number after converting to hex.\r
- The error number is put into the buffer in hex. '255' is the biggest errno we can send.\r
- ex: 162 will be sent as A2.\r
-\r
- @param errno the error number that will be sent\r
- **/\r
-VOID\r
-EFIAPI\r
-SendError (\r
- IN UINT8 ErrorNum\r
- )\r
-{\r
- //\r
- // Replace _, or old data, with current errno\r
- //\r
- gError[1] = mHexToStr [ErrorNum >> 4];\r
- gError[2] = mHexToStr [ErrorNum & 0x0f];\r
-\r
- SendPacket (gError); // send buffer\r
-}\r
-\r
-\r
-\r
-/**\r
- Send 'OK' when the function is done executing successfully.\r
- **/\r
-VOID\r
-EFIAPI\r
-SendSuccess (\r
- VOID\r
- )\r
-{\r
- SendPacket ("OK"); // send buffer\r
-}\r
-\r
-\r
-/**\r
- Send empty packet to specify that particular command/functionality is not supported.\r
- **/\r
-VOID\r
-EFIAPI\r
-SendNotSupported (\r
- VOID\r
- )\r
-{\r
- SendPacket ("");\r
-}\r
-\r
-\r
-\r
-\r
-\r
-/**\r
- Translates the EFI mapping to GDB mapping\r
-\r
- @param EFIExceptionType EFI Exception that is being processed\r
- @retval UINTN that corresponds to EFIExceptionType's GDB exception type number\r
- **/\r
-UINT8\r
-ConvertEFItoGDBtype (\r
- IN EFI_EXCEPTION_TYPE EFIExceptionType\r
- )\r
-{\r
- UINTN i;\r
-\r
- for (i=0; i < MaxEfiException() ; i++) {\r
- if (gExceptionType[i].Exception == EFIExceptionType) {\r
- return gExceptionType[i].SignalNo;\r
- }\r
- }\r
- return GDB_SIGTRAP; // this is a GDB trap\r
-}\r
-\r
-\r
-/** "m addr,length"\r
- Find the Length of the area to read and the start addres. Finally, pass them to\r
- another function, TransferFromMemToOutBufAndSend, that will read from that memory space and\r
- send it as a packet.\r
- **/\r
-\r
-VOID\r
-EFIAPI\r
-ReadFromMemory (\r
- CHAR8 *PacketData\r
- )\r
-{\r
- UINTN Address;\r
- UINTN Length;\r
- CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the address in hex chars\r
- CHAR8 *AddrBufPtr; // pointer to the address buffer\r
- CHAR8 *InBufPtr; /// pointer to the input buffer\r
-\r
- AddrBufPtr = AddressBuffer;\r
- InBufPtr = &PacketData[1];\r
- while (*InBufPtr != ',') {\r
- *AddrBufPtr++ = *InBufPtr++;\r
- }\r
- *AddrBufPtr = '\0';\r
-\r
- InBufPtr++; // this skips ',' in the buffer\r
-\r
- /* Error checking */\r
- if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {\r
- SendError (GDB_EBADMEMADDRBUFSIZE);\r
- return;\r
- }\r
-\r
- // 2 = 'm' + ','\r
- if (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - 2 >= MAX_LENGTH_SIZE) {\r
- SendError (GDB_EBADMEMLENGTH);\r
- return;\r
- }\r
-\r
- Address = AsciiStrHexToUintn (AddressBuffer);\r
- Length = AsciiStrHexToUintn (InBufPtr);\r
-\r
- TransferFromMemToOutBufAndSend (Length, (unsigned char *)Address);\r
-}\r
-\r
-\r
-/** "M addr,length :XX..."\r
- Find the Length of the area in bytes to write and the start addres. Finally, pass them to\r
- another function, TransferFromInBufToMem, that will write to that memory space the info in\r
- the input buffer.\r
- **/\r
-VOID\r
-EFIAPI\r
-WriteToMemory (\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- UINTN Address;\r
- UINTN Length;\r
- UINTN MessageLength;\r
- CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the Address in hex chars\r
- CHAR8 LengthBuffer[MAX_LENGTH_SIZE]; // the buffer that will hold the Length in hex chars\r
- CHAR8 *AddrBufPtr; // pointer to the Address buffer\r
- CHAR8 *LengthBufPtr; // pointer to the Length buffer\r
- CHAR8 *InBufPtr; /// pointer to the input buffer\r
-\r
- AddrBufPtr = AddressBuffer;\r
- LengthBufPtr = LengthBuffer;\r
- InBufPtr = &PacketData[1];\r
-\r
- while (*InBufPtr != ',') {\r
- *AddrBufPtr++ = *InBufPtr++;\r
- }\r
- *AddrBufPtr = '\0';\r
-\r
- InBufPtr++; // this skips ',' in the buffer\r
-\r
- while (*InBufPtr != ':') {\r
- *LengthBufPtr++ = *InBufPtr++;\r
- }\r
- *LengthBufPtr = '\0';\r
-\r
- InBufPtr++; // this skips ':' in the buffer\r
-\r
- Address = AsciiStrHexToUintn (AddressBuffer);\r
- Length = AsciiStrHexToUintn (LengthBuffer);\r
-\r
- /* Error checking */\r
-\r
- //Check if Address is not too long.\r
- if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {\r
- SendError (GDB_EBADMEMADDRBUFSIZE);\r
- return;\r
- }\r
-\r
- //Check if message length is not too long\r
- if (AsciiStrLen(LengthBuffer) >= MAX_LENGTH_SIZE) {\r
- SendError (GDB_EBADMEMLENGBUFSIZE);\r
- return;\r
- }\r
-\r
- // Check if Message is not too long/short.\r
- // 3 = 'M' + ',' + ':'\r
- MessageLength = (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - AsciiStrLen(LengthBuffer) - 3);\r
- if (MessageLength != (2*Length)) {\r
- //Message too long/short. New data is not the right size.\r
- SendError (GDB_EBADMEMDATASIZE);\r
- return;\r
- }\r
- TransferFromInBufToMem (Length, (unsigned char *)Address, InBufPtr);\r
-}\r
-\r
-/**\r
- Parses breakpoint packet data and captures Breakpoint type, Address and length.\r
- In case of an error, function returns particular error code. Returning 0 meaning\r
- no error.\r
-\r
- @param PacketData Pointer to the payload data for the packet.\r
- @param Type Breakpoint type\r
- @param Address Breakpoint address\r
- @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)\r
-\r
- @retval 1 Success\r
- @retval {other} Particular error code\r
-\r
-**/\r
-UINTN\r
-ParseBreakpointPacket (\r
- IN CHAR8 *PacketData,\r
- OUT UINTN *Type,\r
- OUT UINTN *Address,\r
- OUT UINTN *Length\r
- )\r
-{\r
- CHAR8 AddressBuffer[MAX_ADDR_SIZE];\r
- CHAR8 *AddressBufferPtr;\r
- CHAR8 *PacketDataPtr;\r
-\r
- PacketDataPtr = &PacketData[1];\r
- AddressBufferPtr = AddressBuffer;\r
-\r
- *Type = AsciiStrHexToUintn (PacketDataPtr);\r
-\r
- //Breakpoint/watchpoint type should be between 0 to 4\r
- if (*Type > 4) {\r
- return 22; //EINVAL: Invalid argument.\r
- }\r
-\r
- //Skip ',' in the buffer.\r
- while (*PacketDataPtr++ != ',');\r
-\r
- //Parse Address information\r
- while (*PacketDataPtr != ',') {\r
- *AddressBufferPtr++ = *PacketDataPtr++;\r
- }\r
- *AddressBufferPtr = '\0';\r
-\r
- //Check if Address is not too long.\r
- if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) {\r
- return 40; //EMSGSIZE: Message size too long.\r
- }\r
-\r
- *Address = AsciiStrHexToUintn (AddressBuffer);\r
-\r
- PacketDataPtr++; //This skips , in the buffer\r
-\r
- //Parse Length information\r
- *Length = AsciiStrHexToUintn (PacketDataPtr);\r
-\r
- //Length should be 1, 2 or 4 bytes\r
- if (*Length > 4) {\r
- return 22; //EINVAL: Invalid argument\r
- }\r
-\r
- return 0; //0 = No error\r
-}\r
-\r
-\r
-\r
-/**\r
- Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param GdbExceptionType GDB exception type\r
- **/\r
-VOID\r
-GdbSendTSignal (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINT8 GdbExceptionType\r
- )\r
-{\r
- CHAR8 TSignalBuffer[128];\r
- CHAR8 *TSignalPtr;\r
-\r
- TSignalPtr = &TSignalBuffer[0];\r
-\r
- //Construct TSignal packet\r
- *TSignalPtr++ = 'T';\r
-\r
- //\r
- // replace _, or previous value, with Exception type\r
- //\r
- *TSignalPtr++ = mHexToStr [GdbExceptionType >> 4];\r
- *TSignalPtr++ = mHexToStr [GdbExceptionType & 0x0f];\r
-\r
- ProcessorSendTSignal (SystemContext, GdbExceptionType, TSignalPtr, sizeof (TSignalBuffer) - 2);\r
-\r
- SendPacket (TSignalBuffer);\r
-}\r
-\r
-VOID\r
-GdbFWrite (\r
- IN UINTN Fd,\r
- IN CHAR8 *Data,\r
- IN UINTN DataSize\r
- )\r
-{\r
- CHAR8 Buffer[128];\r
-\r
- AsciiSPrint (Buffer, sizeof (Buffer), "Fwrite,%x,%x,%x", Fd, Data, DataSize);\r
- SendPacket (Buffer);\r
-\r
- for( ; ; ) {\r
- ReceivePacket (gInBuffer, MAX_BUF_SIZE);\r
-\r
- switch (gInBuffer[0]) {\r
- case 'm':\r
- ReadFromMemory (gInBuffer);\r
- break;\r
-\r
- case 'M':\r
- WriteToMemory (gInBuffer);\r
- break;\r
-\r
- case 'F':\r
- return;\r
- }\r
- }\r
-}\r
-\r
-\r
-VOID\r
-GdbFPutString (\r
- IN CHAR8 *String\r
- )\r
-{\r
- UINTN Len = AsciiStrSize (String);\r
-\r
- GdbFWrite (2, String, Len);\r
-}\r
-\r
-\r
-/**\r
- Exception Hanldler for GDB. It will be called for all exceptions\r
- registered via the gExceptionType[] array.\r
-\r
- @param ExceptionType Exception that is being processed\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-GdbExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- UINT8 GdbExceptionType;\r
- CHAR8 *Ptr;\r
-\r
- if (ProcessorControlC (ExceptionType, SystemContext)) {\r
- // We tried to process a control C handler and there is nothing to do\r
- return;\r
- }\r
-\r
- GdbExceptionType = ConvertEFItoGDBtype (ExceptionType);\r
- GdbSendTSignal (SystemContext, GdbExceptionType);\r
-\r
- for( ; ; ) {\r
- ReceivePacket (gInBuffer, MAX_BUF_SIZE);\r
-\r
- switch (gInBuffer[0]) {\r
- case '?':\r
- GdbSendTSignal (SystemContext, GdbExceptionType);\r
- break;\r
-\r
- case 'c':\r
- ContinueAtAddress (SystemContext, gInBuffer);\r
- return;\r
-\r
- case 'D':\r
- // gdb wants to disconnect so return "OK" packet since.\r
- SendSuccess ();\r
- return;\r
-\r
- case 'g':\r
- ReadGeneralRegisters (SystemContext);\r
- break;\r
-\r
- case 'G':\r
- WriteGeneralRegisters (SystemContext, gInBuffer);\r
- break;\r
-\r
- case 'H':\r
- //Return "OK" packet since we don't have more than one thread.\r
- SendSuccess ();\r
- break;\r
-\r
- case 'm':\r
- ReadFromMemory (gInBuffer);\r
- break;\r
-\r
- case 'M':\r
- WriteToMemory (gInBuffer);\r
- break;\r
-\r
- case 'P':\r
- WriteNthRegister (SystemContext, gInBuffer);\r
- break;\r
-\r
- //\r
- // Still debugging this code. Not used in Darwin\r
- //\r
- case 'q':\r
- // General Query Packets\r
- if (AsciiStrnCmp (gInBuffer, "qSupported", 10) == 0) {\r
- // return what we currently support, we don't parse what gdb suports\r
- AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE);\r
- SendPacket (gOutBuffer);\r
- } else if (AsciiStrnCmp (gInBuffer, "qXfer:libraries:read::", 22) == 0) {\r
- // \91qXfer:libraries:read::offset,length\r
- // gInBuffer[22] is offset string, ++Ptr is length string\92\r
- for (Ptr = &gInBuffer[22]; *Ptr != ','; Ptr++);\r
-\r
- // Not sure if multi-radix support is required. Currently only support decimal\r
- QxferLibrary (AsciiStrHexToUintn (&gInBuffer[22]), AsciiStrHexToUintn (++Ptr));\r
- } else if (AsciiStrnCmp (gInBuffer, "qOffsets", 8) == 0) {\r
- AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "Text=1000;Data=f000;Bss=f000");\r
- SendPacket (gOutBuffer);\r
- } else if (AsciiStrnCmp (gInBuffer, "qAttached", 9) == 0) {\r
- // remote server attached to an existing process\r
- SendPacket ("1");\r
- } else {\r
- //Send empty packet\r
- SendNotSupported ();\r
- }\r
- break;\r
-\r
- case 's':\r
- SingleStep (SystemContext, gInBuffer);\r
- return;\r
-\r
- case 'z':\r
- RemoveBreakPoint (SystemContext, gInBuffer);\r
- break;\r
-\r
- case 'Z':\r
- InsertBreakPoint (SystemContext, gInBuffer);\r
- break;\r
-\r
- default:\r
- //Send empty packet\r
- SendNotSupported ();\r
- break;\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-\r
-\r
+++ /dev/null
-/** @file\r
- Private include file for GDB stub\r
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
-\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef __GCC_DEBUG_AGENT_INTERNAL__\r
-#define __GCC_DEBUG_AGENT_INTERNAL__\r
-\r
-#include <Uefi.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/GdbSerialLib.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/CacheMaintenanceLib.h>\r
-#include <Library/DebugAgentTimerLib.h>\r
-#include <Library/DebugAgentLib.h>\r
-\r
-#include <IndustryStandard/PeImage.h>\r
-#include <Protocol/DebugSupport.h>\r
-\r
-extern CONST CHAR8 mHexToStr[];\r
-\r
-// maximum size of input and output buffers\r
-// This value came from the show remote command of the gdb we tested against\r
-#define MAX_BUF_SIZE 2000\r
-\r
-// maximum size of address buffer\r
-#define MAX_ADDR_SIZE 32\r
-\r
-// maximum size of register number buffer\r
-#define MAX_REG_NUM_BUF_SIZE 32\r
-\r
-// maximum size of length buffer\r
-#define MAX_LENGTH_SIZE 32\r
-\r
-// maximum size of T signal members\r
-#define MAX_T_SIGNAL_SIZE 64\r
-\r
-// the mask used to clear all the cache\r
-#define TF_BIT 0x00000100\r
-\r
-\r
-//\r
-// GDB Signal definitions - generic names for interrupts\r
-//\r
-#define GDB_SIGINT 2 // Interrupt process via ctrl-c\r
-#define GDB_SIGILL 4 // Illegal instruction\r
-#define GDB_SIGTRAP 5 // Trace Trap (Breakpoint and SingleStep)\r
-#define GDB_SIGEMT 7 // Emulator Trap\r
-#define GDB_SIGFPE 8 // Floating point exception\r
-#define GDB_SIGSEGV 11 // Setgment violation, page fault\r
-\r
-\r
-//\r
-// GDB File I/O Error values, zero means no error\r
-// Includes all general GDB Unix like error values\r
-//\r
-#define GDB_EBADMEMADDRBUFSIZE 11 // the buffer that stores memory Address to be read from/written to is not the right size\r
-#define GDB_EBADMEMLENGBUFSIZE 12 // the buffer that stores Length is not the right size\r
-#define GDB_EBADMEMLENGTH 13 // Length, the given number of bytes to read or write, is not the right size\r
-#define GDB_EBADMEMDATA 14 // one of the bytes or nibbles of the memory is leess than 0\r
-#define GDB_EBADMEMDATASIZE 15 // the memory data, 'XX..', is too short or too long\r
-#define GDB_EBADBUFSIZE 21 // the buffer created is not the correct size\r
-#define GDB_EINVALIDARG 31 // argument is invalid\r
-#define GDB_ENOSPACE 41 //\r
-#define GDB_EINVALIDBRKPOINTTYPE 51 // the breakpoint type is not recognized\r
-#define GDB_EINVALIDREGNUM 61 // given register number is not valid: either <0 or >=Number of Registers\r
-#define GDB_EUNKNOWN 255 // unknown\r
-\r
-\r
-//\r
-// These devices are open by GDB so we can just read and write to them\r
-//\r
-#define GDB_STDIN 0x00\r
-#define GDB_STDOUT 0x01\r
-#define GDB_STDERR 0x02\r
-\r
-//\r
-//Define Register size for different architectures\r
-//\r
-#if defined (MDE_CPU_IA32)\r
-#define REG_SIZE 32\r
-#elif defined (MDE_CPU_X64)\r
-#define REG_SIZE 64\r
-#elif defined (MDE_CPU_ARM)\r
-#define REG_SIZE 32\r
-#endif\r
-\r
-\r
-typedef struct {\r
- EFI_EXCEPTION_TYPE Exception;\r
- UINT8 SignalNo;\r
-} EFI_EXCEPTION_TYPE_ENTRY;\r
-\r
-\r
-#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)\r
-\r
-//\r
-// Byte packed structure for DR6\r
-// 32-bits on IA-32\r
-// 64-bits on X64. The upper 32-bits on X64 are reserved\r
-//\r
-typedef union {\r
- struct {\r
- UINT32 B0:1; // Breakpoint condition detected\r
- UINT32 B1:1; // Breakpoint condition detected\r
- UINT32 B2:1; // Breakpoint condition detected\r
- UINT32 B3:1; // Breakpoint condition detected\r
- UINT32 Reserved_1:9; // Reserved\r
- UINT32 BD:1; // Debug register access detected\r
- UINT32 BS:1; // Single step\r
- UINT32 BT:1; // Task switch\r
- UINT32 Reserved_2:16; // Reserved\r
- } Bits;\r
- UINTN UintN;\r
-} IA32_DR6;\r
-\r
-//\r
-// Byte packed structure for DR7\r
-// 32-bits on IA-32\r
-// 64-bits on X64. The upper 32-bits on X64 are reserved\r
-//\r
-typedef union {\r
- struct {\r
- UINT32 L0:1; // Local breakpoint enable\r
- UINT32 G0:1; // Global breakpoint enable\r
- UINT32 L1:1; // Local breakpoint enable\r
- UINT32 G1:1; // Global breakpoint enable\r
- UINT32 L2:1; // Local breakpoint enable\r
- UINT32 G2:1; // Global breakpoint enable\r
- UINT32 L3:1; // Local breakpoint enable\r
- UINT32 G3:1; // Global breakpoint enable\r
- UINT32 LE:1; // Local exact breakpoint enable\r
- UINT32 GE:1; // Global exact breakpoint enable\r
- UINT32 Reserved_1:3; // Reserved\r
- UINT32 GD:1; // Global detect enable\r
- UINT32 Reserved_2:2; // Reserved\r
- UINT32 RW0:2; // Read/Write field\r
- UINT32 LEN0:2; // Length field\r
- UINT32 RW1:2; // Read/Write field\r
- UINT32 LEN1:2; // Length field\r
- UINT32 RW2:2; // Read/Write field\r
- UINT32 LEN2:2; // Length field\r
- UINT32 RW3:2; // Read/Write field\r
- UINT32 LEN3:2; // Length field\r
- } Bits;\r
- UINTN UintN;\r
-} IA32_DR7;\r
-\r
-#endif /* if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) */\r
-\r
-typedef enum {\r
- InstructionExecution, //Hardware breakpoint\r
- DataWrite, //watch\r
- DataRead, //rwatch\r
- DataReadWrite, //awatch\r
- SoftwareBreakpoint, //Software breakpoint\r
- NotSupported\r
-} BREAK_TYPE;\r
-\r
-//\r
-// Array of exception types that need to be hooked by the debugger\r
-//\r
-extern EFI_EXCEPTION_TYPE_ENTRY gExceptionType[];\r
-\r
-//\r
-// If the periodic callback is called while we are processing an F packet we need\r
-// to let the callback know to not read from the serail stream as it could steal\r
-// characters from the F reponse packet\r
-//\r
-extern BOOLEAN gProcessingFPacket;\r
-\r
-\r
-/**\r
- Return the number of entries in the gExceptionType[]\r
-\r
- @retval UINTN, the number of entries in the gExceptionType[] array.\r
- **/\r
-UINTN\r
-MaxEfiException (\r
- VOID\r
- );\r
-\r
-\r
-/**\r
- Check to see if the ISA is supported.\r
- ISA = Instruction Set Architecture\r
-\r
- @retval TRUE if Isa is supported,\r
- FALSE otherwise.\r
- **/\r
-BOOLEAN\r
-CheckIsa (\r
- IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa\r
- );\r
-\r
-\r
-/**\r
- Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param GdbExceptionType GDB exception type\r
- **/\r
-\r
-VOID\r
-GdbSendTSignal (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINT8 GdbExceptionType\r
- );\r
-\r
-\r
-/**\r
- Translates the EFI mapping to GDB mapping\r
-\r
- @param EFIExceptionType EFI Exception that is being processed\r
- @retval UINTN that corresponds to EFIExceptionType's GDB exception type number\r
- **/\r
-UINT8\r
-ConvertEFItoGDBtype (\r
- IN EFI_EXCEPTION_TYPE EFIExceptionType\r
- );\r
-\r
-\r
-/**\r
- Empties the given buffer\r
- @param *Buf pointer to the first element in buffer to be emptied\r
- **/\r
-VOID\r
-EmptyBuffer (\r
- IN CHAR8 *Buf\r
- );\r
-\r
-\r
-/**\r
- Converts an 8-bit Hex Char into a INTN.\r
-\r
- @param Char - the hex character to be converted into UINTN\r
- @retval a INTN, from 0 to 15, that corressponds to Char\r
- -1 if Char is not a hex character\r
- **/\r
-INTN\r
-HexCharToInt (\r
- IN CHAR8 Char\r
- );\r
-\r
-\r
-/** 'E NN'\r
- Send an error with the given error number after converting to hex.\r
- The error number is put into the buffer in hex. '255' is the biggest errno we can send.\r
- ex: 162 will be sent as A2.\r
-\r
- @param errno the error number that will be sent\r
- **/\r
-VOID\r
-EFIAPI\r
-SendError (\r
- IN UINT8 ErrorNum\r
- );\r
-\r
-\r
-/**\r
- Send 'OK' when the function is done executing successfully.\r
- **/\r
-VOID\r
-SendSuccess (\r
- VOID\r
- );\r
-\r
-\r
-/**\r
- Send empty packet to specify that particular command/functionality is not supported.\r
- **/\r
-VOID\r
-SendNotSupported (\r
- VOID\r
- );\r
-\r
-/** ‘p n’\r
- Reads the n-th register's value into an output buffer and sends it as a packet\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer This is the input buffer received from gdb server\r
- **/\r
-VOID\r
-ReadNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- );\r
-\r
-\r
-/** ‘g’\r
- Reads the general registers into an output buffer and sends it as a packet\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-ReadGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- );\r
-\r
-\r
-/** ‘P n...=r...’\r
- Writes the new value of n-th register received into the input buffer to the n-th register\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer This is the input buffer received from gdb server\r
- **/\r
-VOID\r
-WriteNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- );\r
-\r
-\r
-/** ‘G XX...’\r
- Writes the new values received into the input buffer to the general registers\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Pointer to the input buffer received from gdb server\r
- **/\r
-\r
-VOID\r
-WriteGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- );\r
-\r
-\r
-/** ‘m addr,length ’\r
- Find the Length of the area to read and the start addres. Finally, pass them to\r
- another function, TransferFromMemToOutBufAndSend, that will read from that memory space and\r
- send it as a packet.\r
-\r
- @param *PacketData Pointer to Payload data for the packet\r
- **/\r
-VOID\r
-ReadFromMemory (\r
- IN CHAR8 *PacketData\r
- );\r
-\r
-\r
-/** ‘M addr,length :XX...’\r
- Find the Length of the area in bytes to write and the start addres. Finally, pass them to\r
- another function, TransferFromInBufToMem, that will write to that memory space the info in\r
- the input buffer.\r
-\r
- @param PacketData Pointer to Payload data for the packet\r
- **/\r
-VOID\r
-WriteToMemory (\r
- IN CHAR8 *PacketData\r
- );\r
-\r
-\r
-/** ‘c [addr ]’\r
- Continue. addr is Address to resume. If addr is omitted, resume at current\r
- Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param *PacketData Pointer to PacketData\r
- **/\r
-\r
-VOID\r
-ContinueAtAddress (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- );\r
-\r
-\r
-/** ‘s [addr ]’\r
- Single step. addr is the Address at which to resume. If addr is omitted, resume\r
- at same Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param PacketData Pointer to Payload data for the packet\r
- **/\r
-VOID\r
-SingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- );\r
-\r
-/**\r
- Insert Single Step in the SystemContext\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-AddSingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- );\r
-\r
-/**\r
- Remove Single Step in the SystemContext\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-RemoveSingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\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
-\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 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
-RemoveBreakPoint(\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- );\r
-\r
-\r
-/**\r
- Exception Hanldler for GDB. It will be called for all exceptions\r
- registered via the gExceptionType[] array.\r
-\r
- @param ExceptionType Exception that is being processed\r
- @param SystemContext Register content at time of the exception\r
-\r
- **/\r
-VOID\r
-EFIAPI\r
-GdbExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- );\r
-\r
-\r
-/**\r
- Periodic callback for GDB. This function is used to catch a ctrl-c or other\r
- break in type command from GDB.\r
-\r
- @param SystemContext Register content at time of the call\r
-\r
- **/\r
-VOID\r
-EFIAPI\r
-GdbPeriodicCallBack (\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- );\r
-\r
-\r
-/**\r
- Make two serail consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.\r
-\r
- These console show up on the remote system running GDB\r
-\r
-**/\r
-\r
-VOID\r
-GdbInitializeSerialConsole (\r
- VOID\r
- );\r
-\r
-\r
-/**\r
- Send a GDB Remote Serial Protocol Packet\r
-\r
- $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',\r
- the packet teminating character '#' and the two digit checksum.\r
-\r
- If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up\r
- in an infinit loop. This is so if you unplug the debugger code just keeps running\r
-\r
- @param PacketData Payload data for the packet\r
-\r
- @retval Number of bytes of packet data sent.\r
-\r
-**/\r
-UINTN\r
-SendPacket (\r
- IN CHAR8 *PacketData\r
- );\r
-\r
-\r
-/**\r
- Receive a GDB Remote Serial Protocol Packet\r
-\r
- $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',\r
- the packet teminating character '#' and the two digit checksum.\r
-\r
- If host re-starts sending a packet without ending the previous packet, only the last valid packet is processed.\r
- (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)\r
-\r
- If an ack '+' is not sent resend the packet\r
-\r
- @param PacketData Payload data for the packet\r
-\r
- @retval Number of bytes of packet data received.\r
-\r
- **/\r
-UINTN\r
-ReceivePacket (\r
- OUT CHAR8 *PacketData,\r
- IN UINTN PacketDataSize\r
- );\r
-\r
-\r
-/**\r
- Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates\r
- the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.\r
-\r
- @param FileDescriptor Device to talk to.\r
- @param Buffer Buffer to hold Count bytes that were read\r
- @param Count Number of bytes to transfer.\r
-\r
- @retval -1 Error\r
- @retval {other} Number of bytes read.\r
-\r
-**/\r
-INTN\r
-GdbRead (\r
- IN INTN FileDescriptor,\r
- OUT VOID *Buffer,\r
- IN UINTN Count\r
- );\r
-\r
-\r
-/**\r
- Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates\r
- nothing was written. On error -1 is returned.\r
-\r
- @param FileDescriptor Device to talk to.\r
- @param Buffer Buffer to hold Count bytes that are to be written\r
- @param Count Number of bytes to transfer.\r
-\r
- @retval -1 Error\r
- @retval {other} Number of bytes written.\r
-\r
-**/\r
-INTN\r
-GdbWrite (\r
- IN INTN FileDescriptor,\r
- OUT CONST VOID *Buffer,\r
- IN UINTN Count\r
- );\r
-\r
-UINTN *\r
-FindPointerToRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber\r
- );\r
-\r
-CHAR8 *\r
-BasicReadRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *OutBufPtr\r
- );\r
-\r
-VOID\r
-TransferFromInBufToMem (\r
- IN UINTN Length,\r
- IN UINT8 *Address,\r
- IN CHAR8 *NewData\r
- );\r
-\r
-VOID\r
-TransferFromMemToOutBufAndSend (\r
- IN UINTN Length,\r
- IN UINT8 *Address\r
- );\r
-\r
-CHAR8 *\r
-BasicWriteRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *InBufPtr\r
- );\r
-\r
-VOID\r
-PrintReg (\r
- EFI_SYSTEM_CONTEXT SystemContext\r
- );\r
-\r
-UINTN\r
-ParseBreakpointPacket (\r
- IN CHAR8 *PacketData,\r
- OUT UINTN *Type,\r
- OUT UINTN *Address,\r
- OUT UINTN *Length\r
- );\r
-\r
-UINTN\r
-GetBreakpointDataAddress (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN BreakpointNumber\r
- );\r
-\r
-UINTN\r
-GetBreakpointDetected (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- );\r
-\r
-BREAK_TYPE\r
-GetBreakpointType (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN BreakpointNumber\r
- );\r
-\r
-UINTN\r
-ConvertLengthData (\r
- IN UINTN Length\r
- );\r
-\r
-EFI_STATUS\r
-FindNextFreeDebugRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- OUT UINTN *Register\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
-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
-EFI_STATUS\r
-DisableDebugRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN Register\r
- );\r
-\r
-VOID\r
-InitializeProcessor (\r
- VOID\r
- );\r
-\r
-/**\r
- Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param GdbExceptionType GDB exception type\r
- **/\r
-VOID\r
-ProcessorSendTSignal (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINT8 GdbExceptionType,\r
- IN OUT CHAR8 *TSignalPtr,\r
- IN UINTN SizeOfBuffer\r
- );\r
-\r
-/**\r
- Check to see if this exception is related to ctrl-c handling.\r
-\r
- @param ExceptionType Exception that is being processed\r
- @param SystemContext Register content at time of the exception\r
-\r
- @return TRUE This was a ctrl-c check that did not find a ctrl-c\r
- @return FALSE This was not a ctrl-c check or some one hit ctrl-c\r
- **/\r
-BOOLEAN\r
-ProcessorControlC (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- );\r
-\r
-\r
-/**\r
- Initialize debug agent.\r
-\r
- This function is used to set up debug enviroment. It may enable interrupts.\r
-\r
- @param[in] InitFlag Init flag is used to decide initialize process.\r
- @param[in] Context Context needed according to InitFlag, it was optional.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-DebugAgentHookExceptions (\r
- IN UINT32 InitFlag,\r
- IN VOID *Context OPTIONAL\r
- );\r
-\r
-\r
-#endif\r
+++ /dev/null
-#/** @file\r
-# Null instance of Debug Agent Library with empty functions.\r
-#\r
-# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
-#\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#\r
-#**/\r
-\r
-[Defines]\r
- INF_VERSION = 0x00010005\r
- BASE_NAME = GdbDebugAgent\r
- FILE_GUID = b9f10c17-6ca0-40b5-9b44-6253cfc7d24b\r
- MODULE_TYPE = BASE\r
- VERSION_STRING = 1.0\r
- LIBRARY_CLASS = DebugAgentLib\r
-\r
-#\r
-# The following information is for reference only and not required by the build tools.\r
-#\r
-# VALID_ARCHITECTURES = IA32 X64 EBC\r
-#\r
-\r
-[Sources.common]\r
- GdbDebugAgent.c\r
-\r
-[Sources.arm]\r
- Arm/Processor.c\r
- Arm/ExceptionSupport.ARMv6.S\r
- Arm/ExceptionSupport.ARMv6.asm\r
-\r
-[Sources.X64]\r
- Ia32/Processor.c\r
-\r
-[Sources.Ia32]\r
- X64/Processor.c\r
-\r
-\r
-[Packages]\r
- MdePkg/MdePkg.dec\r
- MdeModulePkg/MdeModulePkg.dec\r
- EmbeddedPkg/EmbeddedPkg.dec\r
-\r
-[Packages.arm]\r
- ArmPkg/ArmPkg.dec\r
-\r
-[LibraryClasses]\r
- BaseLib\r
- DebugLib\r
- BaseMemoryLib\r
- PcdLib\r
- GdbSerialLib\r
- CacheMaintenanceLib\r
- DebugAgentTimerLib\r
-\r
-[FeaturePcd.common]\r
- gEmbeddedTokenSpaceGuid.PcdGdbSerial\r
-\r
-[FixedPcd.common]\r
- gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount\r
- gEmbeddedTokenSpaceGuid.PcdGdbTimerPeriodMilliseconds\r
-\r
-[FixedPcd.arm]\r
- gArmTokenSpaceGuid.PcdCpuVectorBaseAddress\r
+++ /dev/null
-/** @file\r
- Processor specific parts of the GDB stub\r
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
-\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <GdbDebugAgent.h>\r
-\r
-//\r
-// Array of exception types that need to be hooked by the debugger\r
-// {EFI mapping, GDB mapping}\r
-//\r
-EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {\r
- { EXCEPT_IA32_DIVIDE_ERROR, GDB_SIGFPE },\r
- { EXCEPT_IA32_DEBUG, GDB_SIGTRAP },\r
- { EXCEPT_IA32_NMI, GDB_SIGEMT },\r
- { EXCEPT_IA32_BREAKPOINT, GDB_SIGTRAP },\r
- { EXCEPT_IA32_OVERFLOW, GDB_SIGSEGV },\r
- { EXCEPT_IA32_BOUND, GDB_SIGSEGV },\r
- { EXCEPT_IA32_INVALID_OPCODE, GDB_SIGILL },\r
- { EXCEPT_IA32_DOUBLE_FAULT, GDB_SIGEMT },\r
- { EXCEPT_IA32_STACK_FAULT, GDB_SIGSEGV },\r
- { EXCEPT_IA32_GP_FAULT, GDB_SIGSEGV },\r
- { EXCEPT_IA32_PAGE_FAULT, GDB_SIGSEGV },\r
- { EXCEPT_IA32_FP_ERROR, GDB_SIGEMT },\r
- { EXCEPT_IA32_ALIGNMENT_CHECK, GDB_SIGEMT },\r
- { EXCEPT_IA32_MACHINE_CHECK, GDB_SIGEMT }\r
-};\r
-\r
-\r
-// The offsets of registers SystemContext.\r
-// The fields in the array are in the gdb ordering.\r
-//\r
-//16 regs\r
-UINTN gRegisterOffsets[] = {\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eax),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ecx),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edx),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebx),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esp),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebp),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esi),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edi),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eip),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eflags),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Cs),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ss),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ds),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Es),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Fs),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Gs)\r
-};\r
-\r
-\r
-//Debug only..\r
-VOID\r
-PrintReg (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- Print ((CHAR16 *)L"EAX: %x ", SystemContext.SystemContextIa32->Eax);\r
- Print ((CHAR16 *)L"ECX: %x ", SystemContext.SystemContextIa32->Ecx);\r
- Print ((CHAR16 *)L"EDX: %x ", SystemContext.SystemContextIa32->Edx);\r
- Print ((CHAR16 *)L"EBX: %x ", SystemContext.SystemContextIa32->Ebx);\r
- Print ((CHAR16 *)L"ESP: %x ", SystemContext.SystemContextIa32->Esp);\r
- Print ((CHAR16 *)L"EBP: %x ", SystemContext.SystemContextIa32->Ebp);\r
- Print ((CHAR16 *)L"ESI: %x ", SystemContext.SystemContextIa32->Esi);\r
- Print ((CHAR16 *)L"EDI: %x ", SystemContext.SystemContextIa32->Edi);\r
- Print ((CHAR16 *)L"EIP: %x\n", SystemContext.SystemContextIa32->Eip);\r
- Print ((CHAR16 *)L"EFlags: %x\n", SystemContext.SystemContextIa32->Eflags);\r
-}\r
-\r
-//Debug only..\r
-VOID\r
-PrintDRreg (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- Print ((CHAR16 *)L"DR0: %x ", SystemContext.SystemContextIa32->Dr0);\r
- Print ((CHAR16 *)L"DR1: %x ", SystemContext.SystemContextIa32->Dr1);\r
- Print ((CHAR16 *)L"DR2: %x ", SystemContext.SystemContextIa32->Dr2);\r
- Print ((CHAR16 *)L"DR3: %x ", SystemContext.SystemContextIa32->Dr3);\r
- Print ((CHAR16 *)L"DR6: %x ", SystemContext.SystemContextIa32->Dr6);\r
- Print ((CHAR16 *)L"DR7: %x\n", SystemContext.SystemContextIa32->Dr7);\r
-}\r
-\r
-\r
-/**\r
- Return the number of entries in the gExceptionType[]\r
-\r
- @retval UINTN, the number of entries in the gExceptionType[] array.\r
- **/\r
-UINTN\r
-MaxEfiException (\r
- VOID\r
- )\r
-{\r
- return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);\r
-}\r
-\r
-\r
-/**\r
- Check to see if the ISA is supported.\r
- ISA = Instruction Set Architecture\r
-\r
- @retval TRUE if Isa is supported,\r
- FALSE otherwise.\r
-**/\r
-BOOLEAN\r
-CheckIsa (\r
- IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa\r
- )\r
-{\r
- return (BOOLEAN)(Isa == IsaIa32);\r
-}\r
-\r
-\r
-/**\r
- This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering\r
- It is, by default, set to find the register pointer of the IA32 member\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber The register to which we want to find a pointer\r
- @retval the pointer to the RegNumber-th pointer\r
- **/\r
-UINTN *\r
-FindPointerToRegister(\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber\r
- )\r
-{\r
- UINT8 *TempPtr;\r
- TempPtr = ((UINT8 *)SystemContext.SystemContextIa32) + gRegisterOffsets[RegNumber];\r
- return (UINTN *)TempPtr;\r
-}\r
-\r
-\r
-/**\r
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber the number of the register that we want to read\r
- @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.\r
- @retval the pointer to the next character of the output buffer that is available to be written on.\r
- **/\r
-CHAR8 *\r
-BasicReadRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *OutBufPtr\r
- )\r
-{\r
- UINTN RegSize;\r
-\r
- RegSize = 0;\r
- while (RegSize < REG_SIZE) {\r
- *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];\r
- *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];\r
- RegSize = RegSize + 8;\r
- }\r
- return OutBufPtr;\r
-}\r
-\r
-\r
-/** ‘p n’\r
- Reads the n-th register's value into an output buffer and sends it as a packet\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Pointer to the input buffer received from gdb server\r
- **/\r
-VOID\r
-EFIAPI\r
-ReadNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN RegNumber;\r
- CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)\r
- CHAR8 *OutBufPtr; // pointer to the output buffer\r
-\r
- RegNumber = AsciiStrHexToUintn (&InBuffer[1]);\r
-\r
- if ((RegNumber < 0) || (RegNumber >= sizeof (gRegisterOffsets)/sizeof (UINTN))) {\r
- SendError (GDB_EINVALIDREGNUM);\r
- return;\r
- }\r
-\r
- OutBufPtr = OutBuffer;\r
- OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr);\r
-\r
- *OutBufPtr = '\0'; // the end of the buffer\r
- SendPacket(OutBuffer);\r
-}\r
-\r
-\r
-/** ‘g’\r
- Reads the general registers into an output buffer and sends it as a packet\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-ReadGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- UINTN i;\r
- CHAR8 OutBuffer[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq)\r
- CHAR8 *OutBufPtr; // pointer to the output buffer\r
-\r
- OutBufPtr = OutBuffer;\r
- for(i = 0 ; i < sizeof (gRegisterOffsets)/sizeof (UINTN) ; i++) { // there are only 16 registers to read\r
- OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr);\r
- }\r
-\r
- *OutBufPtr = '\0'; // the end of the buffer\r
- SendPacket(OutBuffer);\r
-}\r
-\r
-\r
-/**\r
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber the number of the register that we want to write\r
- @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.\r
- @retval the pointer to the next character of the input buffer that can be used\r
- **/\r
-CHAR8 *\r
-BasicWriteRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *InBufPtr\r
- )\r
-{\r
- UINTN RegSize;\r
- UINTN TempValue; // the value transferred from a hex char\r
- UINT32 NewValue; // the new value of the RegNumber-th Register\r
-\r
- NewValue = 0;\r
- RegSize = 0;\r
- while (RegSize < REG_SIZE) {\r
- TempValue = HexCharToInt(*InBufPtr++);\r
-\r
- if (TempValue < 0) {\r
- SendError (GDB_EBADMEMDATA);\r
- return NULL;\r
- }\r
-\r
- NewValue += (TempValue << (RegSize+4));\r
- TempValue = HexCharToInt(*InBufPtr++);\r
-\r
- if (TempValue < 0) {\r
- SendError (GDB_EBADMEMDATA);\r
- return NULL;\r
- }\r
-\r
- NewValue += (TempValue << RegSize);\r
- RegSize = RegSize + 8;\r
- }\r
- *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;\r
- return InBufPtr;\r
-}\r
-\r
-\r
-/** ‘P n...=r...’\r
- Writes the new value of n-th register received into the input buffer to the n-th register\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Ponter to the input buffer received from gdb server\r
- **/\r
-VOID\r
-EFIAPI\r
-WriteNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN RegNumber;\r
- CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array\r
- CHAR8 *RegNumBufPtr;\r
- CHAR8 *InBufPtr; // pointer to the input buffer\r
-\r
- // find the register number to write\r
- InBufPtr = &InBuffer[1];\r
- RegNumBufPtr = RegNumBuffer;\r
- while (*InBufPtr != '=') {\r
- *RegNumBufPtr++ = *InBufPtr++;\r
- }\r
- *RegNumBufPtr = '\0';\r
- RegNumber = AsciiStrHexToUintn (RegNumBuffer);\r
-\r
- // check if this is a valid Register Number\r
- if ((RegNumber < 0) || (RegNumber >= sizeof (gRegisterOffsets)/sizeof (UINTN))) {\r
- SendError (GDB_EINVALIDREGNUM);\r
- return;\r
- }\r
- InBufPtr++; // skips the '=' character\r
- BasicWriteRegister (SystemContext, RegNumber, InBufPtr);\r
- SendSuccess();\r
-}\r
-\r
-\r
-/** ‘G XX...’\r
- Writes the new values received into the input buffer to the general registers\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Pointer to the input buffer received from gdb server\r
- **/\r
-VOID\r
-EFIAPI\r
-WriteGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN i;\r
- CHAR8 *InBufPtr; /// pointer to the input buffer\r
-\r
- // check to see if the buffer is the right size which is\r
- // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129\r
- if (AsciiStrLen(InBuffer) != 129) { // 16 regs, 8 hex chars each, and the end '\0' (escape seq)\r
- //Bad message. Message is not the right length\r
- SendError (GDB_EBADBUFSIZE);\r
- return;\r
- }\r
-\r
- InBufPtr = &InBuffer[1];\r
-\r
- // Read the new values for the registers from the input buffer to an array, NewValueArray.\r
- // The values in the array are in the gdb ordering\r
- for(i=0; i < sizeof (gRegisterOffsets)/sizeof (UINTN); i++) { // there are only 16 registers to write\r
- InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr);\r
- }\r
-\r
- SendSuccess();\r
-}\r
-\r
-/** ‘c [addr ]’\r
- Continue. addr is Address to resume. If addr is omitted, resume at current\r
- Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-ContinueAtAddress (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- if (PacketData[1] != '\0') {\r
- SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);\r
- }\r
-}\r
-\r
-\r
-/** ‘s [addr ]’\r
- Single step. addr is the Address at which to resume. If addr is omitted, resume\r
- at same Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-SingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- SendNotSupported();\r
-}\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
-/**\r
- Initialize debug agent.\r
-\r
- This function is used to set up debug environment to support source level debugging.\r
- If certain Debug Agent Library instance has to save some private data in the stack,\r
- this function must work on the mode that doesn't return to the caller, then\r
- the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one\r
- function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is\r
- responsible to invoke the passing-in function at the end of InitializeDebugAgent().\r
-\r
- If the parameter Function is not NULL, Debug Agent Library instance will invoke it by\r
- passing in the Context to be its parameter.\r
-\r
- If Function() is NULL, Debug Agent Library instance will return after setup debug\r
- environment.\r
-\r
- @param[in] InitFlag Init flag is used to decide the initialize process.\r
- @param[in] Context Context needed according to InitFlag; it was optional.\r
- @param[in] Function Continue function called by debug agent library; it was\r
- optional.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-InitializeDebugAgent (\r
- IN UINT32 InitFlag,\r
- IN VOID *Context, OPTIONAL\r
- IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
- )\r
-{\r
- // BugBug: Add the code to build an GDT/IDT\r
-\r
- if (Function != NULL) {\r
- Function (Context);\r
- }\r
-}\r
-\r
+++ /dev/null
-/** @file\r
- Processor specific parts of the GDB stub\r
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
-\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <GdbStubInternal.h>\r
-\r
-//\r
-// Array of exception types that need to be hooked by the debugger\r
-//\r
-EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {\r
- { EXCEPT_X64_DIVIDE_ERROR, GDB_SIGFPE },\r
- { EXCEPT_X64_DEBUG, GDB_SIGTRAP },\r
- { EXCEPT_X64_NMI, GDB_SIGEMT },\r
- { EXCEPT_X64_BREAKPOINT, GDB_SIGTRAP },\r
- { EXCEPT_X64_OVERFLOW, GDB_SIGSEGV },\r
- { EXCEPT_X64_BOUND, GDB_SIGSEGV },\r
- { EXCEPT_X64_INVALID_OPCODE, GDB_SIGILL },\r
- { EXCEPT_X64_DOUBLE_FAULT, GDB_SIGEMT },\r
- { EXCEPT_X64_STACK_FAULT, GDB_SIGSEGV },\r
- { EXCEPT_X64_GP_FAULT, GDB_SIGSEGV },\r
- { EXCEPT_X64_PAGE_FAULT, GDB_SIGSEGV },\r
- { EXCEPT_X64_FP_ERROR, GDB_SIGEMT },\r
- { EXCEPT_X64_ALIGNMENT_CHECK, GDB_SIGEMT },\r
- { EXCEPT_X64_MACHINE_CHECK, GDB_SIGEMT }\r
-};\r
-\r
-\r
-// The offsets of registers SystemContextX64.\r
-// The fields in the array are in the gdb ordering.\r
-// HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs\r
-//\r
-UINTN gRegisterOffsets[] = {\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rax),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rcx),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdx),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbx),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsp),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbp),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsi),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdi),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rip),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rflags),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Cs),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ss),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ds),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Es),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Fs),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Gs),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R8),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R9),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R10),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R11),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R12),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R13),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R14),\r
- OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R15)\r
-};\r
-\r
-\r
-/**\r
- Return the number of entries in the gExceptionType[]\r
-\r
- @retval UINTN, the number of entries in the gExceptionType[] array.\r
- **/\r
-UINTN\r
-MaxEfiException (\r
- VOID\r
- )\r
-{\r
- return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);\r
-}\r
-\r
-\r
-/**\r
- Return the number of entries in the gRegisters[]\r
-\r
- @retval UINTN, the number of entries (registers) in the gRegisters[] array.\r
- **/\r
-UINTN\r
-MaxRegisterCount (\r
- VOID\r
- )\r
-{\r
- return sizeof (gRegisterOffsets)/sizeof (UINTN);\r
-}\r
-\r
-\r
-/**\r
- Check to see if the ISA is supported.\r
- ISA = Instruction Set Architecture\r
-\r
- @retval TRUE if Isa is supported\r
-**/\r
-BOOLEAN\r
-CheckIsa (\r
- IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa\r
- )\r
-{\r
- return (BOOLEAN)(Isa == IsaX64);\r
-}\r
-\r
-\r
-/**\r
- This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering\r
- It is, by default, set to find the register pointer of the X64 member\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber The register to which we want to find a pointer\r
- @retval the pointer to the RegNumber-th pointer\r
- **/\r
-UINTN *\r
-FindPointerToRegister(\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber\r
- )\r
-{\r
- UINT8 *TempPtr;\r
- TempPtr = ((UINT8 *)SystemContext.SystemContextX64) + gRegisterOffsets[RegNumber];\r
- return (UINTN *)TempPtr;\r
-}\r
-\r
-\r
-/**\r
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber the number of the register that we want to read\r
- @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.\r
- @retval the pointer to the next character of the output buffer that is available to be written on.\r
- **/\r
-CHAR8 *\r
-BasicReadRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *OutBufPtr\r
- )\r
-{\r
- UINTN RegSize;\r
-\r
- RegSize = 0;\r
- while (RegSize < 64) {\r
- *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];\r
- *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];\r
- RegSize = RegSize + 8;\r
- }\r
- return OutBufPtr;\r
-}\r
-\r
-\r
-/** ‘p n’\r
- Reads the n-th register's value into an output buffer and sends it as a packet\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Pointer to the input buffer received from gdb server\r
- **/\r
-VOID\r
-ReadNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN RegNumber;\r
- CHAR8 OutBuffer[17]; // 1 reg=16 hex chars, and the end '\0' (escape seq)\r
- CHAR8 *OutBufPtr; // pointer to the output buffer\r
-\r
- RegNumber = AsciiStrHexToUintn (&InBuffer[1]);\r
-\r
- if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {\r
- SendError (GDB_EINVALIDREGNUM);\r
- return;\r
- }\r
-\r
- OutBufPtr = OutBuffer;\r
- OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr);\r
-\r
- *OutBufPtr = '\0'; // the end of the buffer\r
- SendPacket (OutBuffer);\r
-}\r
-\r
-\r
-/** ‘g’\r
- Reads the general registers into an output buffer and sends it as a packet\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-ReadGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- UINTN i;\r
- CHAR8 OutBuffer[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq)\r
- CHAR8 *OutBufPtr; // pointer to the output buffer\r
-\r
- OutBufPtr = OutBuffer;\r
- for(i = 0 ; i < MaxRegisterCount() ; i++) { // there are only 24 registers to read\r
- OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr);\r
- }\r
-\r
- *OutBufPtr = '\0'; // the end of the buffer\r
- SendPacket (OutBuffer);\r
-}\r
-\r
-\r
-/**\r
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param RegNumber the number of the register that we want to write\r
- @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.\r
- @retval the pointer to the next character of the input buffer that can be used\r
- **/\r
-CHAR8 *\r
-BasicWriteRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN UINTN RegNumber,\r
- IN CHAR8 *InBufPtr\r
- )\r
-{\r
- UINTN RegSize;\r
- UINTN TempValue; // the value transferred from a hex char\r
- UINT64 NewValue; // the new value of the RegNumber-th Register\r
-\r
- NewValue = 0;\r
- RegSize = 0;\r
- while (RegSize < 64) {\r
- TempValue = HexCharToInt(*InBufPtr++);\r
-\r
- if (TempValue < 0) {\r
- SendError (GDB_EBADMEMDATA);\r
- return NULL;\r
- }\r
-\r
- NewValue += (TempValue << (RegSize+4));\r
- TempValue = HexCharToInt(*InBufPtr++);\r
-\r
- if (TempValue < 0) {\r
- SendError (GDB_EBADMEMDATA);\r
- return NULL;\r
- }\r
-\r
- NewValue += (TempValue << RegSize);\r
- RegSize = RegSize + 8;\r
- }\r
- *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;\r
- return InBufPtr;\r
-}\r
-\r
-\r
-/** ‘P n...=r...’\r
- Writes the new value of n-th register received into the input buffer to the n-th register\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Ponter to the input buffer received from gdb server\r
- **/\r
-VOID\r
-EFIAPI\r
-WriteNthRegister (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN RegNumber;\r
- CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array\r
- CHAR8 *RegNumBufPtr;\r
- CHAR8 *InBufPtr; // pointer to the input buffer\r
-\r
- // find the register number to write\r
- InBufPtr = &InBuffer[1];\r
- RegNumBufPtr = RegNumBuffer;\r
- while (*InBufPtr != '=') {\r
- *RegNumBufPtr++ = *InBufPtr++;\r
- }\r
- *RegNumBufPtr = '\0';\r
- RegNumber = AsciiStrHexToUintn (RegNumBuffer);\r
-\r
- // check if this is a valid Register Number\r
- if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {\r
- SendError (GDB_EINVALIDREGNUM);\r
- return;\r
- }\r
- InBufPtr++; // skips the '=' character\r
- BasicWriteRegister (SystemContext, RegNumber, InBufPtr);\r
- SendSuccess();\r
-}\r
-\r
-\r
-/** ‘G XX...’\r
- Writes the new values received into the input buffer to the general registers\r
-\r
- @param SystemContext Register content at time of the exception\r
- @param InBuffer Pointer to the input buffer received from gdb server\r
- **/\r
-VOID\r
-EFIAPI\r
-WriteGeneralRegisters (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *InBuffer\r
- )\r
-{\r
- UINTN i;\r
- CHAR8 *InBufPtr; /// pointer to the input buffer\r
-\r
- // check to see if the buffer is the right size which is\r
- // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385\r
- if (AsciiStrLen(InBuffer) != 385) { // 24 regs, 16 hex chars each, and the end '\0' (escape seq)\r
- //Bad message. Message is not the right length\r
- SendError (GDB_EBADBUFSIZE);\r
- return;\r
- }\r
-\r
- InBufPtr = &InBuffer[1];\r
-\r
- // Read the new values for the registers from the input buffer to an array, NewValueArray.\r
- // The values in the array are in the gdb ordering\r
- for(i=0; i < MaxRegisterCount(); i++) { // there are only 16 registers to write\r
- InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr);\r
- }\r
-\r
- SendSuccess();\r
-}\r
-\r
-\r
- /**\r
- Insert Single Step in the SystemContext\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-AddSingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- SystemContext.SystemContextX64->Rflags |= TF_BIT; //Setting the TF bit.\r
-}\r
-\r
-\r
-\r
-/**\r
- Remove Single Step in the SystemContext\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-RemoveSingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- SystemContext.SystemContextX64->Rflags &= ~TF_BIT; // clearing the TF bit.\r
-}\r
-\r
-\r
-\r
-/** ‘c [addr ]’\r
- Continue. addr is Address to resume. If addr is omitted, resume at current\r
- Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-ContinueAtAddress (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- if (PacketData[1] != '\0') {\r
- SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn(&PacketData[1]);\r
- }\r
-}\r
-\r
-\r
-/** ‘s [addr ]’\r
- Single step. addr is the Address at which to resume. If addr is omitted, resume\r
- at same Address.\r
-\r
- @param SystemContext Register content at time of the exception\r
- **/\r
-VOID\r
-EFIAPI\r
-SingleStep (\r
- IN EFI_SYSTEM_CONTEXT SystemContext,\r
- IN CHAR8 *PacketData\r
- )\r
-{\r
- if (PacketData[1] != '\0') {\r
- SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn (&PacketData[1]);\r
- }\r
-\r
- AddSingleStep (SystemContext);\r
-}\r
-\r
-\r
-/**\r
- Returns breakpoint data address from DR0-DR3 based on the input breakpoint\r
- 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\r
- 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
- Returns currently detected breakpoint value based on the register\r
- 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
- Returns Breakpoint type (InstructionExecution, DataWrite, DataRead\r
- or DataReadWrite) 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\r
- field. 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,\r
- Data read 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, Data read\r
- 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
- ‘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
-\r
- if (Status == EFI_UNSUPPORTED) {\r
- Print ((CHAR16 *)L"Not supported\n");\r
- SendNotSupported();\r
- return;\r
- }\r
-\r
- Print ((CHAR16 *)L"Invalid argument\n");\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
-\r
- if (Status == EFI_UNSUPPORTED) {\r
- Print ((CHAR16 *)L"Not supported.\n");\r
- SendNotSupported();\r
- return;\r
- }\r
-\r
- Print ((CHAR16 *)L"No matching register found.\n");\r
- SendError (GDB_ENOSPACE);\r
- return;\r
- }\r
-\r
- //Remove breakpoint\r
- Status = DisableDebugRegister(SystemContext, Register);\r
- if (EFI_ERROR(Status)) {\r
- Print ((CHAR16 *)L"Invalid argument.\n");\r
- SendError (GDB_EINVALIDARG);\r
- return;\r
- }\r
-\r
- SendSuccess ();\r
-}\r
-\r
-\r
-VOID\r
-InitializeProcessor (\r
- VOID\r
- )\r
-{\r
-}\r
-\r
-BOOLEAN\r
-ValidateAddress (\r
- IN VOID *Address\r
- )\r
-{\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN\r
-ValidateException (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- return TRUE;\r
-}\r
-\r
+++ /dev/null
-arm-none-eabi-gcc -march=armv7-a -mthumb t.c -Wl,-nostdlib --emit-relocs\r
-\r
-target remote com7\r
-set debug remote 1 \r
-set remotetimeout 30\r
-set remotelogfile log.txt\r
-add-symbol-file c:/work/edk2/Build/BeagleBoard/DEBUG_GCC48/ARM/BeagleBoardPkg/Sec/Sec/DEBUG/BeagleBoardSec.dll 0x80008360\r
-\r
-\r
-qSupported\r
-Hg0\r
-\r
-Hc-1\r
-qC\r
-qAttached
\ No newline at end of file