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
This commit is contained in:
276
ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.S
Normal file
276
ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.S
Normal file
@@ -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
|
||||
|
273
ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.asm
Normal file
273
ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentException.asm
Normal file
@@ -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
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
Reference in New Issue
Block a user