diff options
author | oliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-09-28 09:52:11 +0000 |
---|---|---|
committer | oliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524> | 2012-09-28 09:52:11 +0000 |
commit | 9d6b024ded89621f1a643d0ddea6904375c4cc67 (patch) | |
tree | 36a79e9e2a288f6b0a7322e903caaac59c6c6a84 /ArmPkg/Library/DebugAgentSymbolsBaseLib | |
parent | 7ea4cf3f595f35373ff57cff997cde0bcea6871f (diff) | |
download | edk2-platforms-9d6b024ded89621f1a643d0ddea6904375c4cc67.tar.xz |
ArmPlatformPkg/Sec: Moved Exception Vector Table to ArmPkg/DebugAgentBaseLib
In case a DebugAgent library is supported for a specific debugger, we would
expect the exception be caught by DebugAgentLib.
The DebugAgentBaseLib exposes the cause of the exception to the user in the
Serial Terminal.
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13765 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg/Library/DebugAgentSymbolsBaseLib')
4 files changed, 942 insertions, 0 deletions
diff --git a/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.S b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.S new file mode 100644 index 0000000000..3c17386766 --- /dev/null +++ b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.S @@ -0,0 +1,276 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR> +# Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR> +# +# 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 <Library/PcdLib.h> + +/* + +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 + + */ + +GCC_ASM_EXPORT(DebugAgentVectorTable) +GCC_ASM_IMPORT(DefaultExceptionHandler) + +.text +#if !defined(__APPLE__) +.fpu neon @ makes vpush/vpop assemble +#endif +.align 5 + + +// +// This code gets copied to the ARM vector table +// ExceptionHandlersStart - ExceptionHandlersEnd gets copied +// +ASM_PFX(DebugAgentVectorTable): + b ASM_PFX(ResetEntry) + b ASM_PFX(UndefinedInstructionEntry) + b ASM_PFX(SoftwareInterruptEntry) + b ASM_PFX(PrefetchAbortEntry) + b ASM_PFX(DataAbortEntry) + b ASM_PFX(ReservedExceptionEntry) + b ASM_PFX(IrqEntry) + b ASM_PFX(FiqEntry) + +ASM_PFX(ResetEntry): + 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,#0 @ ExceptionType + ldr R1,ASM_PFX(CommonExceptionEntry) + bx R1 + +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(IrqEntry): + 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,#6 @ ExceptionType + 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): + .word ASM_PFX(AsmCommonExceptionEntry) + +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 + +#if (FixedPcdGet32(PcdVFPEnabled)) + vpush {d0-d15} @ save vstm registers in case they are used in optimizations +#endif + +/* +VOID +EFIAPI +DefaultExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, R0 + IN OUT EFI_SYSTEM_CONTEXT SystemContext R1 + ) + +*/ + blx ASM_PFX(DefaultExceptionHandler) @ Call exception handler + +#if (FixedPcdGet32(PcdVFPEnabled)) + vpop {d0-d15} +#endif + + ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR + mcr p15, 0, R1, c5, c0, 1 @ Write IFSR + + ldr R1, [SP, #0x44] @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR + mcr p15, 0, R1, c5, c0, 0 @ Write DFSR + + 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/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.asm b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.asm new file mode 100644 index 0000000000..f281c0603f --- /dev/null +++ b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.asm @@ -0,0 +1,273 @@ +//------------------------------------------------------------------------------
+//
+// Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+// Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>
+//
+// 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 <Library/PcdLib.h>
+
+/*
+
+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 DebugAgentVectorTable
+ IMPORT DefaultExceptionHandler
+
+ PRESERVE8
+ AREA DebugAgentException, CODE, READONLY, CODEALIGN, ALIGN=5
+
+//
+// This code gets copied to the ARM vector table
+// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
+//
+DebugAgentVectorTable FUNCTION
+ b ResetEntry
+ b UndefinedInstructionEntry
+ b SoftwareInterruptEntry
+ b PrefetchAbortEntry
+ b DataAbortEntry
+ b ReservedExceptionEntry
+ b IrqEntry
+ b FiqEntry
+ ENDFUNC
+
+ResetEntry
+ 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,#0 ; ExceptionType
+ ldr R1,CommonExceptionEntry
+ bx R1
+
+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
+
+IrqEntry
+ 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,#6 ; 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 AsmCommonExceptionEntry
+
+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
+
+#if (FixedPcdGet32(PcdVFPEnabled))
+ vpush {d0-d15} ; save vstm registers in case they are used in optimizations
+#endif
+
+/*
+VOID
+EFIAPI
+DefaultExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType, R0
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
+ )
+
+*/
+ blx DefaultExceptionHandler ; Call exception handler
+
+#if (FixedPcdGet32(PcdVFPEnabled))
+ vpop {d0-d15}
+#endif
+
+ ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
+ mcr p15, 0, R1, c5, c0, 1 ; Write IFSR
+
+ ldr R1, [SP, #0x44] ; sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR
+ mcr p15, 0, R1, c5, c0, 0 ; Write DFSR
+
+ 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/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c new file mode 100644 index 0000000000..5d986779ee --- /dev/null +++ b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.c @@ -0,0 +1,351 @@ +/** @file
+* Main file supporting the SEC Phase for Versatile Express
+*
+* Copyright (c) 2011-2012, ARM Limited. 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 <Uefi.h>
+#include <Library/ArmLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/PeCoffLib.h>
+
+#include <Pi/PiFirmwareFile.h>
+#include <Pi/PiFirmwareVolume.h>
+
+#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
+ (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
+
+
+// Vector Table for Sec Phase
+VOID
+DebugAgentVectorTable (
+ VOID
+ );
+
+/**
+ Returns the highest bit set of the State field
+
+ @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
+ in the Attributes field.
+ @param FfsHeader Pointer to FFS File Header
+
+
+ @retval the highest bit in the State field
+
+**/
+STATIC
+EFI_FFS_FILE_STATE
+GetFileState (
+ IN UINT8 ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+{
+ EFI_FFS_FILE_STATE FileState;
+ EFI_FFS_FILE_STATE HighestBit;
+
+ FileState = FfsHeader->State;
+
+ if (ErasePolarity != 0) {
+ FileState = (EFI_FFS_FILE_STATE)~FileState;
+ }
+
+ HighestBit = 0x80;
+ while (HighestBit != 0 && (HighestBit & FileState) == 0) {
+ HighestBit >>= 1;
+ }
+
+ return HighestBit;
+}
+
+/**
+ Calculates the checksum of the header of a file.
+ The header is a zero byte checksum, so zero means header is good
+
+ @param FfsHeader Pointer to FFS File Header
+
+ @retval Checksum of the header
+
+**/
+STATIC
+UINT8
+CalculateHeaderChecksum (
+ IN EFI_FFS_FILE_HEADER *FileHeader
+ )
+{
+ UINT8 Sum;
+
+ // Calculate the sum of the header
+ Sum = CalculateSum8 ((CONST VOID*)FileHeader,sizeof(EFI_FFS_FILE_HEADER));
+
+ // State field (since this indicates the different state of file).
+ Sum = (UINT8)(Sum - FileHeader->State);
+
+ // Checksum field of the file is not part of the header checksum.
+ Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);
+
+ return Sum;
+}
+
+EFI_STATUS
+GetFfsFile (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader,
+ IN EFI_FV_FILETYPE FileType,
+ OUT EFI_FFS_FILE_HEADER **FileHeader
+ )
+{
+ UINT64 FvLength;
+ UINTN FileOffset;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ UINT8 ErasePolarity;
+ UINT8 FileState;
+ UINT32 FileLength;
+ UINT32 FileOccupiedSize;
+
+ ASSERT (FwVolHeader->Signature == EFI_FVH_SIGNATURE);
+
+ FvLength = FwVolHeader->FvLength;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
+ FileOffset = FwVolHeader->HeaderLength;
+
+ if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
+ ErasePolarity = 1;
+ } else {
+ ErasePolarity = 0;
+ }
+
+ while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
+ // Get FileState which is the highest bit of the State
+ FileState = GetFileState (ErasePolarity, FfsFileHeader);
+
+ switch (FileState) {
+
+ case EFI_FILE_HEADER_INVALID:
+ FileOffset += sizeof(EFI_FFS_FILE_HEADER);
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
+ break;
+
+ case EFI_FILE_DATA_VALID:
+ case EFI_FILE_MARKED_FOR_UPDATE:
+ if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+ }
+
+ if (FfsFileHeader->Type == FileType) {
+ *FileHeader = FfsFileHeader;
+ return EFI_SUCCESS;
+ }
+
+ FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
+ FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
+
+ FileOffset += FileOccupiedSize;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
+ break;
+
+ case EFI_FILE_DELETED:
+ FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
+ FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
+ FileOffset += FileOccupiedSize;
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
+ break;
+
+ default:
+ return EFI_NOT_FOUND;
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetImageContext (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+{
+ EFI_STATUS Status;
+ UINTN ParsedLength;
+ UINTN SectionSize;
+ UINTN SectionLength;
+ EFI_COMMON_SECTION_HEADER *Section;
+ VOID *EfiImage;
+ UINTN ImageAddress;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ VOID *CodeViewEntryPointer;
+
+ Section = (EFI_COMMON_SECTION_HEADER *)(FfsHeader + 1);
+ SectionSize = *(UINT32 *)(FfsHeader->Size) & 0x00FFFFFF;
+ SectionSize -= sizeof (EFI_FFS_FILE_HEADER);
+ ParsedLength = 0;
+ EfiImage = NULL;
+
+ while (ParsedLength < SectionSize) {
+ if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {
+ EfiImage = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(Section + 1);
+ break;
+ }
+
+ //
+ // Size is 24 bits wide so mask upper 8 bits.
+ // SectionLength is adjusted it is 4 byte aligned.
+ // Go to the next section
+ //
+ SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
+ SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
+ ASSERT (SectionLength != 0);
+ ParsedLength += SectionLength;
+ Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
+ }
+
+ if (EfiImage == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Initialize the Image Context
+ ZeroMem (ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+ ImageContext->Handle = EfiImage;
+ ImageContext->ImageRead = PeCoffLoaderImageReadFromMemory;
+
+ Status = PeCoffLoaderGetImageInfo (ImageContext);
+ if (!EFI_ERROR(Status) && ((VOID*)ImageContext->DebugDirectoryEntryRva != NULL)) {
+ ImageAddress = ImageContext->ImageAddress;
+ if (ImageContext->IsTeImage) {
+ ImageAddress += sizeof (EFI_TE_IMAGE_HEADER) - ((EFI_TE_IMAGE_HEADER*)EfiImage)->StrippedSize;
+ }
+
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(ImageAddress + ImageContext->DebugDirectoryEntryRva);
+ if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ CodeViewEntryPointer = (VOID *) (ImageAddress + (UINTN) DebugEntry->RVA);
+ switch (* (UINT32 *) CodeViewEntryPointer) {
+ case CODEVIEW_SIGNATURE_NB10:
+ ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+ break;
+ case CODEVIEW_SIGNATURE_RSDS:
+ ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+ break;
+ case CODEVIEW_SIGNATURE_MTOC:
+ ImageContext->PdbPointer = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Initialize debug agent.
+
+ This function is used to set up debug environment to support source level debugging.
+ If certain Debug Agent Library instance has to save some private data in the stack,
+ this function must work on the mode that doesn't return to the caller, then
+ the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
+ function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
+ responsible to invoke the passing-in function at the end of InitializeDebugAgent().
+
+ If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by
+ passing in the Context to be its parameter.
+
+ If Function() is NULL, Debug Agent Library instance will return after setup debug
+ environment.
+
+ @param[in] InitFlag Init flag is used to decide the initialize process.
+ @param[in] Context Context needed according to InitFlag; it was optional.
+ @param[in] Function Continue function called by debug agent library; it was
+ optional.
+
+**/
+VOID
+EFIAPI
+InitializeDebugAgent (
+ IN UINT32 InitFlag,
+ IN VOID *Context, OPTIONAL
+ IN DEBUG_AGENT_CONTINUE Function OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FfsHeader;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ // Now we've got UART, make the check:
+ // - The Vector table must be 32-byte aligned
+ //TODO: Define a macro for the ARM Exception Table
+ ASSERT(((UINT32)DebugAgentVectorTable & ARM_VECTOR_TABLE_ALIGNMENT) == 0);
+ ArmWriteVBar (DebugAgentVectorTable);
+
+ // We use InitFlag to know if DebugAgent has been intialized from
+ // Sec (DEBUG_AGENT_INIT_PREMEM_SEC) or PrePi (DEBUG_AGENT_INIT_POSTMEM_SEC)
+ // modules
+ if (InitFlag == DEBUG_AGENT_INIT_PREMEM_SEC) {
+ //
+ // Get the Sec or PrePeiCore module (defined as SEC type module)
+ //
+ Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)PcdGet32(PcdSecureFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);
+ if (!EFI_ERROR(Status)) {
+ Status = GetImageContext (FfsHeader,&ImageContext);
+ if (!EFI_ERROR(Status)) {
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+ }
+ }
+ } else if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) {
+ //
+ // Get the PrePi or PrePeiCore module (defined as SEC type module)
+ //
+ Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)PcdGet32(PcdFvBaseAddress), EFI_FV_FILETYPE_SECURITY_CORE, &FfsHeader);
+ if (!EFI_ERROR(Status)) {
+ Status = GetImageContext (FfsHeader,&ImageContext);
+ if (!EFI_ERROR(Status)) {
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+ }
+ }
+
+ //
+ // Get the PeiCore module (defined as PEI_CORE type module)
+ //
+ Status = GetFfsFile ((EFI_FIRMWARE_VOLUME_HEADER*)PcdGet32(PcdFvBaseAddress), EFI_FV_FILETYPE_PEI_CORE, &FfsHeader);
+ if (!EFI_ERROR(Status)) {
+ Status = GetImageContext (FfsHeader,&ImageContext);
+ if (!EFI_ERROR(Status)) {
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+ }
+ }
+ }
+}
+
+/**
+ 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
+ )
+{
+ return FALSE;
+}
+
diff --git a/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf new file mode 100644 index 0000000000..1cf0b33524 --- /dev/null +++ b/ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf @@ -0,0 +1,42 @@ +#
+# Copyright (c) 2011-2012, ARM Limited. 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.
+#
+#
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DebugAgentSymbolsBaseLib
+ FILE_GUID = 9055e2e0-9b33-11e0-a7d7-0002a5d5c51b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DebugAgentLib
+
+[Sources.common]
+ DebugAgentSymbolsBaseLib.c
+ DebugAgentException.asm | RVCT
+ DebugAgentException.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ ArmLib
+ DebugLib
+ DefaultExceptionHandlerLib
+ PcdLib
+ PeCoffExtraActionLib
+ PeCoffLib
+
+[Pcd]
+ gArmTokenSpaceGuid.PcdSecureFvBaseAddress
+ gArmTokenSpaceGuid.PcdFvBaseAddress
|