diff options
author | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-04-03 00:41:42 +0000 |
---|---|---|
committer | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-04-03 00:41:42 +0000 |
commit | 969eba7b0df70c9aa261eaf005085568b88de87c (patch) | |
tree | bdbc700471085d43dfb70929159f32ddf231a24c /EmbeddedPkg/Library/GdbDebugAgent/Arm | |
parent | 66c0b4461add95d84f74ab8348430adb62ae9e1f (diff) | |
download | edk2-platforms-969eba7b0df70c9aa261eaf005085568b88de87c.tar.xz |
Add the beginning of a GDB based Debug Agent. IA-32 and X64 don't have low level interrupt code yet. I've been testing on ARM.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10334 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EmbeddedPkg/Library/GdbDebugAgent/Arm')
3 files changed, 1147 insertions, 0 deletions
diff --git a/EmbeddedPkg/Library/GdbDebugAgent/Arm/ExceptionSupport.ARMv6.S b/EmbeddedPkg/Library/GdbDebugAgent/Arm/ExceptionSupport.ARMv6.S new file mode 100755 index 0000000000..bb4d17c5ad --- /dev/null +++ b/EmbeddedPkg/Library/GdbDebugAgent/Arm/ExceptionSupport.ARMv6.S @@ -0,0 +1,258 @@ +#------------------------------------------------------------------------------ +# +# Use ARMv6 instruction to operate on a single stack +# +# Copyright (c) 2008-2010 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +/* + +This is the stack constructed by the exception handler (low address to high address) + # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM + Reg Offset + === ====== + R0 0x00 # stmfd SP!,{R0-R12} + R1 0x04 + R2 0x08 + R3 0x0c + R4 0x10 + R5 0x14 + R6 0x18 + R7 0x1c + R8 0x20 + R9 0x24 + R10 0x28 + R11 0x2c + R12 0x30 + SP 0x34 # reserved via adding 0x20 (32) to the SP + LR 0x38 + PC 0x3c + CPSR 0x40 + DFSR 0x44 + DFAR 0x48 + IFSR 0x4c + IFAR 0x50 + + LR 0x54 # SVC Link register (we need to restore it) + + LR 0x58 # pushed by srsfd + CPSR 0x5c + + */ + + +.globl ASM_PFX(ExceptionHandlersStart) +.globl ASM_PFX(ExceptionHandlersEnd) +.globl ASM_PFX(CommonExceptionEntry) +.globl ASM_PFX(AsmCommonExceptionEntry) +.globl ASM_PFX(GdbExceptionHandler) + +.text +.align 3 + + +// +// This code gets copied to the ARM vector table +// ExceptionHandlersStart - ExceptionHandlersEnd gets copied +// +ASM_PFX(ExceptionHandlersStart): + +ASM_PFX(Reset): + b ASM_PFX(Reset) + +ASM_PFX(UndefinedInstruction): + b ASM_PFX(UndefinedInstructionEntry) + +ASM_PFX(SoftwareInterrupt): + b ASM_PFX(SoftwareInterruptEntry) + +ASM_PFX(PrefetchAbort): + b ASM_PFX(PrefetchAbortEntry) + +ASM_PFX(DataAbort): + b ASM_PFX(DataAbortEntry) + +ASM_PFX(ReservedException): + b ASM_PFX(ReservedExceptionEntry) + +ASM_PFX(Irq): + b ASM_PFX(Irq) + +ASM_PFX(Fiq): + b ASM_PFX(FiqEntry) + + +ASM_PFX(UndefinedInstructionEntry): + sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry + srsdb #0x13! @ Store return state on SVC stack + cps #0x13 @ Switch to SVC for common stack + stmfd SP!,{LR} @ Store the link register for the current mode + sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} @ Store the register state + + mov R0,#1 @ ExceptionType + ldr R1,ASM_PFX(CommonExceptionEntry) + bx R1 + +ASM_PFX(SoftwareInterruptEntry): + sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry + srsdb #0x13! @ Store return state on SVC stack + @ We are already in SVC mode + stmfd SP!,{LR} @ Store the link register for the current mode + sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} @ Store the register state + + mov R0,#2 @ ExceptionType + ldr R1,ASM_PFX(CommonExceptionEntry) + bx R1 + +ASM_PFX(PrefetchAbortEntry): + sub LR,LR,#4 + srsdb #0x13! @ Store return state on SVC stack + cps #0x13 @ Switch to SVC for common stack + stmfd SP!,{LR} @ Store the link register for the current mode + sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} @ Store the register state + + mov R0,#3 @ ExceptionType + ldr R1,ASM_PFX(CommonExceptionEntry) + bx R1 + +ASM_PFX(DataAbortEntry): + sub LR,LR,#8 + srsdb #0x13! @ Store return state on SVC stack + cps #0x13 @ Switch to SVC for common stack + stmfd SP!,{LR} @ Store the link register for the current mode + sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} @ Store the register state + + mov R0,#4 + ldr R1,ASM_PFX(CommonExceptionEntry) + bx R1 + +ASM_PFX(ReservedExceptionEntry): + srsdb #0x13! @ Store return state on SVC stack + cps #0x13 @ Switch to SVC for common stack + stmfd SP!,{LR} @ Store the link register for the current mode + sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} @ Store the register state + + mov R0,#5 + ldr R1,ASM_PFX(CommonExceptionEntry) + bx R1 + +ASM_PFX(FiqEntry): + sub LR,LR,#4 + srsdb #0x13! @ Store return state on SVC stack + cps #0x13 @ Switch to SVC for common stack + stmfd SP!,{LR} @ Store the link register for the current mode + sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} @ Store the register state + @ Since we have already switch to SVC R8_fiq - R12_fiq + @ never get used or saved + mov R0,#7 @ ExceptionType + ldr R1,ASM_PFX(CommonExceptionEntry) + bx R1 + +// +// This gets patched by the C code that patches in the vector table +// +ASM_PFX(CommonExceptionEntry): + .byte 0x12 + .byte 0x34 + .byte 0x56 + .byte 0x78 + +ASM_PFX(ExceptionHandlersEnd): + +// +// This code runs from CpuDxe driver loaded address. It is patched into +// CommonExceptionEntry. +// +ASM_PFX(AsmCommonExceptionEntry): + mrc p15, 0, R1, c6, c0, 2 @ Read IFAR + str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR + + mrc p15, 0, R1, c5, c0, 1 @ Read IFSR + str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR + + mrc p15, 0, R1, c6, c0, 0 @ Read DFAR + str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR + + mrc p15, 0, R1, c5, c0, 0 @ Read DFSR + str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR + + ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack + str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR + + add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR + and R3, R1, #0x1f @ Check CPSR to see if User or System Mode + cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1df)) + cmpne R3, #0x10 @ + stmeqed R2, {lr}^ @ save unbanked lr + @ else + stmneed R2, {lr} @ save SVC lr + + + ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd + @ Check to see if we have to adjust for Thumb entry + sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType ==2)) { + cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb + bhi NoAdjustNeeded + + tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry + addne R5, R5, #2 @ PC += 2@ + str R5,[SP,#0x58] @ Update LR value pused by srsfd + +NoAdjustNeeded: + + str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC + + sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack + str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP + + @ R0 is ExceptionType + mov R1,SP @ R1 is SystemContext + +/* +VOID +EFIAPI +GdbExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, R0 + IN OUT EFI_SYSTEM_CONTEXT SystemContext R1 + ) + +*/ + blx ASM_PFX(GdbExceptionHandler) @ Call exception handler + + ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC + str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored + + ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR + str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored + + add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry + add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR + and R1, R1, #0x1f @ Check to see if User or System Mode + cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f)) + cmpne R1, #0x10 @ + ldmeqed R2, {lr}^ @ restore unbanked lr + @ else + ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR} + + ldmfd SP!,{R0-R12} @ Restore general purpose registers + @ Exception handler can not change SP + + add SP,SP,#0x20 @ Clear out the remaining stack space + ldmfd SP!,{LR} @ restore the link register for this context + rfefd SP! @ return from exception via srsfd stack slot + diff --git a/EmbeddedPkg/Library/GdbDebugAgent/Arm/ExceptionSupport.ARMv6.asm b/EmbeddedPkg/Library/GdbDebugAgent/Arm/ExceptionSupport.ARMv6.asm new file mode 100755 index 0000000000..3dccf5b077 --- /dev/null +++ b/EmbeddedPkg/Library/GdbDebugAgent/Arm/ExceptionSupport.ARMv6.asm @@ -0,0 +1,259 @@ +//------------------------------------------------------------------------------ +// +// Use ARMv6 instruction to operate on a single stack +// +// Copyright (c) 2008-2010 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + + +/* + +This is the stack constructed by the exception handler (low address to high address) + # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM + Reg Offset + === ====== + R0 0x00 # stmfd SP!,{R0-R12} + R1 0x04 + R2 0x08 + R3 0x0c + R4 0x10 + R5 0x14 + R6 0x18 + R7 0x1c + R8 0x20 + R9 0x24 + R10 0x28 + R11 0x2c + R12 0x30 + SP 0x34 # reserved via adding 0x20 (32) to the SP + LR 0x38 + PC 0x3c + CPSR 0x40 + DFSR 0x44 + DFAR 0x48 + IFSR 0x4c + IFAR 0x50 + + LR 0x54 # SVC Link register (we need to restore it) + + LR 0x58 # pushed by srsfd + CPSR 0x5c + + */ + + + EXPORT ExceptionHandlersStart + EXPORT ExceptionHandlersEnd + EXPORT CommonExceptionEntry + EXPORT AsmCommonExceptionEntry + IMPORT GdbExceptionHandler + + PRESERVE8 + AREA DxeExceptionHandlers, CODE, READONLY + +// +// This code gets copied to the ARM vector table +// ExceptionHandlersStart - ExceptionHandlersEnd gets copied +// +ExceptionHandlersStart + +Reset + b Reset + +UndefinedInstruction + b UndefinedInstructionEntry + +SoftwareInterrupt + b SoftwareInterruptEntry + +PrefetchAbort + b PrefetchAbortEntry + +DataAbort + b DataAbortEntry + +ReservedException + b ReservedExceptionEntry + +Irq + b Irq + +Fiq + b FiqEntry + + +UndefinedInstructionEntry + sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry + srsfd #0x13! ; Store return state on SVC stack + cps #0x13 ; Switch to SVC for common stack + stmfd SP!,{LR} ; Store the link register for the current mode + sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} ; Store the register state + + mov R0,#1 ; ExceptionType + ldr R1,CommonExceptionEntry; + bx R1 + +SoftwareInterruptEntry + sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry + srsfd #0x13! ; Store return state on SVC stack + ; We are already in SVC mode + stmfd SP!,{LR} ; Store the link register for the current mode + sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} ; Store the register state + + mov R0,#2 ; ExceptionType + ldr R1,CommonExceptionEntry + bx R1 + +PrefetchAbortEntry + sub LR,LR,#4 + srsfd #0x13! ; Store return state on SVC stack + cps #0x13 ; Switch to SVC for common stack + stmfd SP!,{LR} ; Store the link register for the current mode + sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} ; Store the register state + + mov R0,#3 ; ExceptionType + ldr R1,CommonExceptionEntry + bx R1 + +DataAbortEntry + sub LR,LR,#8 + srsfd #0x13! ; Store return state on SVC stack + cps #0x13 ; Switch to SVC for common stack + stmfd SP!,{LR} ; Store the link register for the current mode + sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} ; Store the register state + + mov R0,#4 ; ExceptionType + ldr R1,CommonExceptionEntry + bx R1 + +ReservedExceptionEntry + srsfd #0x13! ; Store return state on SVC stack + cps #0x13 ; Switch to SVC for common stack + stmfd SP!,{LR} ; Store the link register for the current mode + sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} ; Store the register state + + mov R0,#5 ; ExceptionType + ldr R1,CommonExceptionEntry + bx R1 + +FiqEntry + sub LR,LR,#4 + srsfd #0x13! ; Store return state on SVC stack + cps #0x13 ; Switch to SVC for common stack + stmfd SP!,{LR} ; Store the link register for the current mode + sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR + stmfd SP!,{R0-R12} ; Store the register state + ; Since we have already switch to SVC R8_fiq - R12_fiq + ; never get used or saved + mov R0,#7 ; ExceptionType + ldr R1,CommonExceptionEntry + bx R1 + +// +// This gets patched by the C code that patches in the vector table +// +CommonExceptionEntry + dcd 0x12345678 + +ExceptionHandlersEnd + +// +// This code runs from CpuDxe driver loaded address. It is patched into +// CommonExceptionEntry. +// +AsmCommonExceptionEntry + mrc p15, 0, R1, c6, c0, 2 ; Read IFAR + str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR + + mrc p15, 0, R1, c5, c0, 1 ; Read IFSR + str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR + + mrc p15, 0, R1, c6, c0, 0 ; Read DFAR + str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR + + mrc p15, 0, R1, c5, c0, 0 ; Read DFSR + str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR + + ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack + str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR + + add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR + and R3, R1, #0x1f ; Check CPSR to see if User or System Mode + cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df)) + cmpne R3, #0x10 ; + stmeqed R2, {lr}^ ; save unbanked lr + ; else + stmneed R2, {lr} ; save SVC lr + + + ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd + ; Check to see if we have to adjust for Thumb entry + sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType ==2)) { + cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb + bhi NoAdjustNeeded + + tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry + addne R5, R5, #2 ; PC += 2; + str R5,[SP,#0x58] ; Update LR value pused by srsfd + +NoAdjustNeeded + + str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC + + sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack + str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP + + ; R0 is ExceptionType + mov R1,SP ; R1 is SystemContext + +/* +VOID +EFIAPI +GdbExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, R0 + IN OUT EFI_SYSTEM_CONTEXT SystemContext R1 + ) + +*/ + blx GdbExceptionHandler ; Call exception handler + + ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC + str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored + + ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR + str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored + + add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry + add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR + and R1, R1, #0x1f ; Check to see if User or System Mode + cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f)) + cmpne R1, #0x10 ; + ldmeqed R2, {lr}^ ; restore unbanked lr + ; else + ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR} + + ldmfd SP!,{R0-R12} ; Restore general purpose registers + ; Exception handler can not change SP + + add SP,SP,#0x20 ; Clear out the remaining stack space + ldmfd SP!,{LR} ; restore the link register for this context + rfefd SP! ; return from exception via srsfd stack slot + + END + + diff --git a/EmbeddedPkg/Library/GdbDebugAgent/Arm/Processor.c b/EmbeddedPkg/Library/GdbDebugAgent/Arm/Processor.c new file mode 100755 index 0000000000..e09e18d6c1 --- /dev/null +++ b/EmbeddedPkg/Library/GdbDebugAgent/Arm/Processor.c @@ -0,0 +1,630 @@ +/** @file
+ Processor specific parts of the GDB stub
+
+ Copyright (c) 2008-2010, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <GdbDebugAgent.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ArmLib.h>
+
+//
+// Externs from the exception handler assembly file
+//
+VOID
+ExceptionHandlersStart (
+ VOID
+ );
+
+VOID
+ExceptionHandlersEnd (
+ VOID
+ );
+
+VOID
+CommonExceptionEntry (
+ VOID
+ );
+
+VOID
+AsmCommonExceptionEntry (
+ VOID
+ );
+
+
+//
+// Array of exception types that need to be hooked by the debugger
+// (efi, gdb) //efi number
+//
+EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
+ { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP },
+ { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },
+ { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP },
+ { EXCEPT_ARM_DATA_ABORT, GDB_SIGTRAP }, // GDB_SIGEMT
+ { EXCEPT_ARM_RESERVED, GDB_SIGTRAP }, // GDB_SIGILL
+ { EXCEPT_ARM_FIQ, GDB_SIGINT } // Used for ctrl-c
+};
+
+// Shut up some annoying RVCT warnings
+#ifdef __CC_ARM
+#pragma diag_suppress 1296
+#endif
+
+UINTN gRegisterOffsets[] = {
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC),
+ 0x00000F01, // f0
+ 0x00000F02,
+ 0x00000F03,
+ 0x00000F11, // f1
+ 0x00000F12,
+ 0x00000F13,
+ 0x00000F21, // f2
+ 0x00000F22,
+ 0x00000F23,
+ 0x00000F31, // f3
+ 0x00000F32,
+ 0x00000F33,
+ 0x00000F41, // f4
+ 0x00000F42,
+ 0x00000F43,
+ 0x00000F51, // f5
+ 0x00000F52,
+ 0x00000F53,
+ 0x00000F61, // f6
+ 0x00000F62,
+ 0x00000F63,
+ 0x00000F71, // f7
+ 0x00000F72,
+ 0x00000F73,
+ 0x00000FFF, // fps
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR)
+};
+
+// restore warnings for RVCT
+#ifdef __CC_ARM
+#pragma diag_default 1296
+#endif
+
+
+/**
+ Return the number of entries in the gExceptionType[]
+
+ @retval UINTN, the number of entries in the gExceptionType[] array.
+ **/
+UINTN
+MaxEfiException (
+ VOID
+ )
+{
+ return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
+}
+
+
+
+
+/**
+ Check to see if the ISA is supported.
+ ISA = Instruction Set Architecture
+
+ @retval TRUE if Isa is supported
+
+**/
+BOOLEAN
+CheckIsa (
+ IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
+ )
+{
+ if (Isa == IsaArm) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/**
+ This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
+ It is, by default, set to find the register pointer of the ARM member
+ @param SystemContext Register content at time of the exception
+ @param RegNumber The register to which we want to find a pointer
+ @retval the pointer to the RegNumber-th pointer
+ **/
+UINTN *
+FindPointerToRegister(
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber
+ )
+{
+ UINT8 *TempPtr;
+ ASSERT(gRegisterOffsets[RegNumber] < 0xF00);
+ TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];
+ return (UINT32 *)TempPtr;
+}
+
+
+/**
+ Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
+ @param SystemContext Register content at time of the exception
+ @param RegNumber the number of the register that we want to read
+ @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
+ @retval the pointer to the next character of the output buffer that is available to be written on.
+ **/
+CHAR8 *
+BasicReadRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber,
+ IN CHAR8 *OutBufPtr
+ )
+{
+ UINTN RegSize;
+ CHAR8 Char;
+
+ if (gRegisterOffsets[RegNumber] > 0xF00) {
+ AsciiSPrint(OutBufPtr, 9, "00000000");
+ OutBufPtr += 8;
+ return OutBufPtr;
+ }
+
+ RegSize = 0;
+ while (RegSize < 32) {
+ Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
+ if ((Char >= 'A') && (Char <= 'F')) {
+ Char = Char - 'A' + 'a';
+ }
+ *OutBufPtr++ = Char;
+
+ Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
+ if ((Char >= 'A') && (Char <= 'F')) {
+ Char = Char - 'A' + 'a';
+ }
+ *OutBufPtr++ = Char;
+
+ RegSize = RegSize + 8;
+ }
+ return OutBufPtr;
+}
+
+
+/** ‘p n’
+ Reads the n-th register's value into an output buffer and sends it as a packet
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Pointer to the input buffer received from gdb server
+ **/
+VOID
+ReadNthRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN RegNumber;
+ CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
+ CHAR8 *OutBufPtr; // pointer to the output buffer
+
+ RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
+
+ if (RegNumber >= (sizeof (gRegisterOffsets)/sizeof (UINTN))) {
+ SendError (GDB_EINVALIDREGNUM);
+ return;
+ }
+
+ OutBufPtr = OutBuffer;
+ OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
+
+ *OutBufPtr = '\0'; // the end of the buffer
+ SendPacket(OutBuffer);
+}
+
+
+/** ‘g’
+ Reads the general registers into an output buffer and sends it as a packet
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+ReadGeneralRegisters (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN Index;
+ // a UINT32 takes 8 ascii characters
+ CHAR8 OutBuffer[(sizeof (gRegisterOffsets) * 2) + 1];
+ CHAR8 *OutBufPtr;
+
+ // It is not safe to allocate pool here....
+ OutBufPtr = OutBuffer;
+ for (Index = 0; Index < (sizeof (gRegisterOffsets)/sizeof (UINTN)); Index++) {
+ OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);
+ }
+
+ *OutBufPtr = '\0';
+ SendPacket(OutBuffer);
+}
+
+
+/**
+ Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
+ @param SystemContext Register content at time of the exception
+ @param RegNumber the number of the register that we want to write
+ @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
+ @retval the pointer to the next character of the input buffer that can be used
+ **/
+CHAR8 *
+BasicWriteRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber,
+ IN CHAR8 *InBufPtr
+ )
+{
+ UINTN RegSize;
+ UINTN TempValue; // the value transferred from a hex char
+ UINT32 NewValue; // the new value of the RegNumber-th Register
+
+ if (gRegisterOffsets[RegNumber] > 0xF00) {
+ return InBufPtr + 8;
+ }
+
+ NewValue = 0;
+ RegSize = 0;
+ while (RegSize < 32) {
+ TempValue = HexCharToInt(*InBufPtr++);
+
+ if ((INTN)TempValue < 0) {
+ SendError (GDB_EBADMEMDATA);
+ return NULL;
+ }
+
+ NewValue += (TempValue << (RegSize+4));
+ TempValue = HexCharToInt(*InBufPtr++);
+
+ if ((INTN)TempValue < 0) {
+ SendError (GDB_EBADMEMDATA);
+ return NULL;
+ }
+
+ NewValue += (TempValue << RegSize);
+ RegSize = RegSize + 8;
+ }
+ *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
+ return InBufPtr;
+}
+
+
+/** ‘P n...=r...’
+ Writes the new value of n-th register received into the input buffer to the n-th register
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Ponter to the input buffer received from gdb server
+ **/
+VOID
+WriteNthRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN RegNumber;
+ CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
+ CHAR8 *RegNumBufPtr;
+ CHAR8 *InBufPtr; // pointer to the input buffer
+
+ // find the register number to write
+ InBufPtr = &InBuffer[1];
+ RegNumBufPtr = RegNumBuffer;
+ while (*InBufPtr != '=') {
+ *RegNumBufPtr++ = *InBufPtr++;
+ }
+ *RegNumBufPtr = '\0';
+ RegNumber = AsciiStrHexToUintn (RegNumBuffer);
+
+ // check if this is a valid Register Number
+ if (RegNumber >= (sizeof (gRegisterOffsets)/sizeof (UINTN))) {
+ SendError (GDB_EINVALIDREGNUM);
+ return;
+ }
+ InBufPtr++; // skips the '=' character
+ BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
+ SendSuccess();
+}
+
+
+/** ‘G XX...’
+ Writes the new values received into the input buffer to the general registers
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Pointer to the input buffer received from gdb server
+ **/
+
+VOID
+EFIAPI
+WriteGeneralRegisters (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN i;
+ CHAR8 *InBufPtr; /// pointer to the input buffer
+ UINTN MinLength;
+ UINTN RegisterCount = (sizeof (gRegisterOffsets)/sizeof (UINTN));
+
+ MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format
+
+ if (AsciiStrLen(InBuffer) < MinLength) {
+ //Bad message. Message is not the right length
+ SendError (GDB_EBADBUFSIZE);
+ return;
+ }
+
+ InBufPtr = &InBuffer[1];
+
+ // Read the new values for the registers from the input buffer to an array, NewValueArray.
+ // The values in the array are in the gdb ordering
+ for(i = 0; i < RegisterCount; i++) {
+ InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
+ }
+
+ SendSuccess ();
+}
+
+
+
+
+/** ‘c [addr ]’
+ Continue. addr is Address to resume. If addr is omitted, resume at current
+ Address.
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+ContinueAtAddress (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ if (PacketData[1] != '\0') {
+ SystemContext.SystemContextArm->PC = AsciiStrHexToUintn(&PacketData[1]);
+ }
+}
+
+
+/** ‘s [addr ]’
+ Single step. addr is the Address at which to resume. If addr is omitted, resume
+ at same Address.
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+SingleStep (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ SendNotSupported();
+}
+
+
+VOID
+EFIAPI
+InsertBreakPoint (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ SendNotSupported ();
+}
+
+VOID
+EFIAPI
+RemoveBreakPoint (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ SendNotSupported ();
+}
+
+
+/** + Send the T signal with the given exception type (in gdb order) and possibly + with n:r pairs related to the watchpoints + + @param SystemContext Register content at time of the exception + @param GdbExceptionType GDB exception type + **/ +VOID +ProcessorSendTSignal ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT8 GdbExceptionType, + IN OUT CHAR8 *TSignalPtr, + IN UINTN SizeOfBuffer + ) +{ + *TSignalPtr = '\0'; +} +
+/**
+ Check to see if this exception is related to ctrl-c handling.
+
+ In this scheme we dedicate FIQ to the ctrl-c handler so it is
+ independent of the rest of the system.
+
+ SaveAndSetDebugTimerInterrupt () can be used to
+
+ @param ExceptionType Exception that is being processed
+ @param SystemContext Register content at time of the exception
+
+ @return TRUE This was a ctrl-c check that did not find a ctrl-c
+ @return FALSE This was not a ctrl-c check or some one hit ctrl-c
+ **/
+BOOLEAN
+ProcessorControlC (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ BOOLEAN Return = TRUE;
+
+ if (ExceptionType != EXCEPT_ARM_FIQ) {
+ // Skip it as it is not related to ctrl-c
+ return FALSE;
+ }
+
+ while (TRUE) { + if (!GdbIsCharAvailable ()) { + // + // No characters are pending so exit the loop + // + Return = TRUE; + break; + } + + if (GdbGetChar () == 0x03) { + // + // We have a ctrl-c so exit and process exception for ctrl-c + // + Return = FALSE; + break; + } + } +
+ DebugAgentTimerEndOfInterrupt ();
+
+ // Force an exit from the exception handler as we are done
+ return Return;
+}
+
+
+/**
+ Enable/Disable the interrupt of debug timer and return the interrupt state
+ prior to the operation.
+
+ If EnableStatus is TRUE, enable the interrupt of debug timer.
+ If EnableStatus is FALSE, disable the interrupt of debug timer.
+
+ @param[in] EnableStatus Enable/Disable.
+
+ @return FALSE always.
+
+**/
+BOOLEAN
+EFIAPI
+SaveAndSetDebugTimerInterrupt (
+ IN BOOLEAN EnableStatus
+ )
+{
+ BOOLEAN FiqEnabled;
+
+ FiqEnabled = ArmGetFiqState ();
+
+ if (EnableStatus) {
+ DebugAgentTimerSetPeriod (100);
+ ArmEnableFiq ();
+ } else {
+ DebugAgentTimerSetPeriod (0);
+ ArmDisableFiq ();
+ }
+
+ return FiqEnabled;
+}
+
+VOID
+GdbFPutString (
+ IN CHAR8 *String
+ );
+
+/**
+ Initialize debug agent.
+
+ This function is used to set up debug enviroment. It may enable interrupts.
+
+ @param[in] InitFlag Init flag is used to decide initialize process.
+ @param[in] Context Context needed according to InitFlag, it was optional.
+
+**/
+VOID
+EFIAPI
+InitializeDebugAgent (
+ IN UINT32 InitFlag,
+ IN VOID *Context OPTIONAL
+ )
+{ + UINTN Offset;
+ UINTN Length;
+ BOOLEAN IrqEnabled;
+ BOOLEAN FiqEnabled;
+ UINT32 *VectorBase;
+
+ + //
+ // Disable interrupts
+ //
+ IrqEnabled = ArmGetInterruptState ();
+ ArmDisableInterrupts ();
+
+ //
+ // EFI does not use the FIQ, but a debugger might so we must disable
+ // as we take over the exception vectors.
+ //
+ FiqEnabled = ArmGetFiqState ();
+ ArmDisableFiq ();
+
+ //
+ // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.
+ //
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
+
+ //
+ // Reserve space for the exception handlers
+ //
+ VectorBase = (UINT32 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress);
+
+
+ // Copy our assembly code into the page that contains the exception vectors.
+ CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);
+
+ //
+ // Patch in the common Assembly exception handler
+ //
+ Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
+ *(UINTN *) (((UINT8 *)VectorBase) + Offset) = (UINTN)AsmCommonExceptionEntry;
+
+ // Flush Caches since we updated executable stuff
+ InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
+
+ DebugAgentTimerIntialize ();
+
+ if (FiqEnabled) {
+ ArmEnableFiq ();
+ }
+
+ if (IrqEnabled) {
+ ArmEnableInterrupts ();
+ }
+
+ return;
+}
+
|