ARM Packages: Fixed line endings

This large code change only modifies the line endings to be CRLF to be
compliant with the EDK2 coding convention document.



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14088 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin
2013-01-25 11:28:06 +00:00
parent 5767f22fca
commit 1e57a46299
280 changed files with 48862 additions and 48862 deletions

View File

@@ -1,191 +1,191 @@
#------------------------------------------------------------------------------
#
# Copyright (c) 2008 - 2010, Apple Inc. 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.
#
#------------------------------------------------------------------------------
.text
.align 3
GCC_ASM_EXPORT(ExceptionHandlersStart)
GCC_ASM_EXPORT(ExceptionHandlersEnd)
GCC_ASM_EXPORT(CommonExceptionEntry)
GCC_ASM_EXPORT(AsmCommonExceptionEntry)
GCC_ASM_EXPORT(CommonCExceptionHandler)
ASM_PFX(ExceptionHandlersStart):
ASM_PFX(Reset):
b ASM_PFX(ResetEntry)
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(IrqEntry)
ASM_PFX(Fiq):
b ASM_PFX(FiqEntry)
ASM_PFX(ResetEntry):
srsdb #0x13! @ Store return state on SVC 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,#0
ldr R1,ASM_PFX(CommonExceptionEntry)
bx R1
ASM_PFX(UndefinedInstructionEntry):
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
ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1
ASM_PFX(SoftwareInterruptEntry):
srsdb #0x13! @ Store return state on SVC 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,#2
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
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
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
mov r0,#7
ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1
ASM_PFX(CommonExceptionEntry):
.byte 0x12
.byte 0x34
.byte 0x56
.byte 0x78
ASM_PFX(ExceptionHandlersEnd):
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
and r1, r1, #0x1f @ Check to see if User or System Mode
cmp r1, #0x1f
cmpne r1, #0x10
add R2, SP, #0x38 @ Store it in EFI_SYSTEM_CONTEXT_ARM.LR
ldmneed r2, {lr}^ @ User or System mode, use unbanked register
ldmneed r2, {lr} @ All other modes used banked register
ldr R1, [SP, #0x58] @ PC is the LR pushed by srsdb
str R1, [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 exception type
mov R1,SP @ Prepare System Context pointer as an argument for the exception handler
blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
ldr R2,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
str R2,[SP,#0x5c] @ Store it back to srsdb stack slot so it can be restored
ldr R2,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
str R2,[SP,#0x58] @ Store it back to srsdb stack slot so it can be restored
ldmfd SP!,{R0-R12} @ Restore general purpose registers
@ Exception handler can not change SP or LR as we would blow chunks
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 srsdb stack slot
#------------------------------------------------------------------------------
#
# Copyright (c) 2008 - 2010, Apple Inc. 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.
#
#------------------------------------------------------------------------------
.text
.align 3
GCC_ASM_EXPORT(ExceptionHandlersStart)
GCC_ASM_EXPORT(ExceptionHandlersEnd)
GCC_ASM_EXPORT(CommonExceptionEntry)
GCC_ASM_EXPORT(AsmCommonExceptionEntry)
GCC_ASM_EXPORT(CommonCExceptionHandler)
ASM_PFX(ExceptionHandlersStart):
ASM_PFX(Reset):
b ASM_PFX(ResetEntry)
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(IrqEntry)
ASM_PFX(Fiq):
b ASM_PFX(FiqEntry)
ASM_PFX(ResetEntry):
srsdb #0x13! @ Store return state on SVC 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,#0
ldr R1,ASM_PFX(CommonExceptionEntry)
bx R1
ASM_PFX(UndefinedInstructionEntry):
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
ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1
ASM_PFX(SoftwareInterruptEntry):
srsdb #0x13! @ Store return state on SVC 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,#2
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
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
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
mov r0,#7
ldr r1,ASM_PFX(CommonExceptionEntry)
bx r1
ASM_PFX(CommonExceptionEntry):
.byte 0x12
.byte 0x34
.byte 0x56
.byte 0x78
ASM_PFX(ExceptionHandlersEnd):
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
and r1, r1, #0x1f @ Check to see if User or System Mode
cmp r1, #0x1f
cmpne r1, #0x10
add R2, SP, #0x38 @ Store it in EFI_SYSTEM_CONTEXT_ARM.LR
ldmneed r2, {lr}^ @ User or System mode, use unbanked register
ldmneed r2, {lr} @ All other modes used banked register
ldr R1, [SP, #0x58] @ PC is the LR pushed by srsdb
str R1, [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 exception type
mov R1,SP @ Prepare System Context pointer as an argument for the exception handler
blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
ldr R2,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
str R2,[SP,#0x5c] @ Store it back to srsdb stack slot so it can be restored
ldr R2,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
str R2,[SP,#0x58] @ Store it back to srsdb stack slot so it can be restored
ldmfd SP!,{R0-R12} @ Restore general purpose registers
@ Exception handler can not change SP or LR as we would blow chunks
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 srsdb stack slot

View File

@@ -1,152 +1,152 @@
//------------------------------------------------------------------------------
//
// Copyright (c) 2008 - 2009, Apple Inc. 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.
//
//------------------------------------------------------------------------------
EXPORT ExceptionHandlersStart
EXPORT ExceptionHandlersEnd
EXPORT CommonExceptionEntry
EXPORT AsmCommonExceptionEntry
IMPORT CommonCExceptionHandler
PRESERVE8
AREA DxeExceptionHandlers, CODE, READONLY
ExceptionHandlersStart
Reset
b ResetEntry
UndefinedInstruction
b UndefinedInstructionEntry
SoftwareInterrupt
b SoftwareInterruptEntry
PrefetchAbort
b PrefetchAbortEntry
DataAbort
b DataAbortEntry
ReservedException
b ReservedExceptionEntry
Irq
b IrqEntry
Fiq
b FiqEntry
ResetEntry
stmfd SP!,{R0-R1}
mov R0,#0
ldr R1,CommonExceptionEntry
bx R1
UndefinedInstructionEntry
stmfd SP!,{R0-R1}
mov R0,#1
ldr R1,CommonExceptionEntry
bx R1
SoftwareInterruptEntry
stmfd SP!,{R0-R1}
mov R0,#2
ldr R1,CommonExceptionEntry
bx R1
PrefetchAbortEntry
stmfd SP!,{R0-R1}
mov R0,#3
SUB LR,LR,#4
ldr R1,CommonExceptionEntry
bx R1
DataAbortEntry
stmfd SP!,{R0-R1}
mov R0,#4
SUB LR,LR,#8
ldr R1,CommonExceptionEntry
bx R1
ReservedExceptionEntry
stmfd SP!,{R0-R1}
mov R0,#5
ldr R1,CommonExceptionEntry
bx R1
IrqEntry
stmfd SP!,{R0-R1}
mov R0,#6
SUB LR,LR,#4
ldr R1,CommonExceptionEntry
bx R1
FiqEntry
stmfd SP!,{R0-R1}
mov R0,#7
SUB LR,LR,#4
ldr R1,CommonExceptionEntry
bx R1
CommonExceptionEntry
dcd 0x12345678
ExceptionHandlersEnd
AsmCommonExceptionEntry
mrc p15, 0, r1, c6, c0, 2 ; Read IFAR
stmfd SP!,{R1} ; Store the IFAR
mrc p15, 0, r1, c5, c0, 1 ; Read IFSR
stmfd SP!,{R1} ; Store the IFSR
mrc p15, 0, r1, c6, c0, 0 ; Read DFAR
stmfd SP!,{R1} ; Store the DFAR
mrc p15, 0, r1, c5, c0, 0 ; Read DFSR
stmfd SP!,{R1} ; Store the DFSR
mrs R1,SPSR ; Read SPSR (which is the pre-exception CPSR)
stmfd SP!,{R1} ; Store the SPSR
stmfd SP!,{LR} ; Store the link register (which is the pre-exception PC)
stmfd SP,{SP,LR}^ ; Store user/system mode stack pointer and link register
nop ; Required by ARM architecture
SUB SP,SP,#0x08 ; Adjust stack pointer
stmfd SP!,{R2-R12} ; Store general purpose registers
ldr R3,[SP,#0x50] ; Read saved R1 from the stack (it was saved by the exception entry routine)
ldr R2,[SP,#0x4C] ; Read saved R0 from the stack (it was saved by the exception entry routine)
stmfd SP!,{R2-R3} ; Store general purpose registers R0 and R1
mov R1,SP ; Prepare System Context pointer as an argument for the exception handler
sub SP,SP,#4 ; Adjust SP to preserve 8-byte alignment
blx CommonCExceptionHandler ; Call exception handler
add SP,SP,#4 ; Adjust SP back to where we were
ldr R2,[SP,#0x40] ; Load CPSR from context, in case it has changed
MSR SPSR_cxsf,R2 ; Store it back to the SPSR to be restored when exiting this handler
ldmfd SP!,{R0-R12} ; Restore general purpose registers
ldm SP,{SP,LR}^ ; Restore user/system mode stack pointer and link register
nop ; Required by ARM architecture
add SP,SP,#0x08 ; Adjust stack pointer
ldmfd SP!,{LR} ; Restore the link register (which is the pre-exception PC)
add SP,SP,#0x1C ; Clear out the remaining stack space
movs PC,LR ; Return from exception
END
//------------------------------------------------------------------------------
//
// Copyright (c) 2008 - 2009, Apple Inc. 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.
//
//------------------------------------------------------------------------------
EXPORT ExceptionHandlersStart
EXPORT ExceptionHandlersEnd
EXPORT CommonExceptionEntry
EXPORT AsmCommonExceptionEntry
IMPORT CommonCExceptionHandler
PRESERVE8
AREA DxeExceptionHandlers, CODE, READONLY
ExceptionHandlersStart
Reset
b ResetEntry
UndefinedInstruction
b UndefinedInstructionEntry
SoftwareInterrupt
b SoftwareInterruptEntry
PrefetchAbort
b PrefetchAbortEntry
DataAbort
b DataAbortEntry
ReservedException
b ReservedExceptionEntry
Irq
b IrqEntry
Fiq
b FiqEntry
ResetEntry
stmfd SP!,{R0-R1}
mov R0,#0
ldr R1,CommonExceptionEntry
bx R1
UndefinedInstructionEntry
stmfd SP!,{R0-R1}
mov R0,#1
ldr R1,CommonExceptionEntry
bx R1
SoftwareInterruptEntry
stmfd SP!,{R0-R1}
mov R0,#2
ldr R1,CommonExceptionEntry
bx R1
PrefetchAbortEntry
stmfd SP!,{R0-R1}
mov R0,#3
SUB LR,LR,#4
ldr R1,CommonExceptionEntry
bx R1
DataAbortEntry
stmfd SP!,{R0-R1}
mov R0,#4
SUB LR,LR,#8
ldr R1,CommonExceptionEntry
bx R1
ReservedExceptionEntry
stmfd SP!,{R0-R1}
mov R0,#5
ldr R1,CommonExceptionEntry
bx R1
IrqEntry
stmfd SP!,{R0-R1}
mov R0,#6
SUB LR,LR,#4
ldr R1,CommonExceptionEntry
bx R1
FiqEntry
stmfd SP!,{R0-R1}
mov R0,#7
SUB LR,LR,#4
ldr R1,CommonExceptionEntry
bx R1
CommonExceptionEntry
dcd 0x12345678
ExceptionHandlersEnd
AsmCommonExceptionEntry
mrc p15, 0, r1, c6, c0, 2 ; Read IFAR
stmfd SP!,{R1} ; Store the IFAR
mrc p15, 0, r1, c5, c0, 1 ; Read IFSR
stmfd SP!,{R1} ; Store the IFSR
mrc p15, 0, r1, c6, c0, 0 ; Read DFAR
stmfd SP!,{R1} ; Store the DFAR
mrc p15, 0, r1, c5, c0, 0 ; Read DFSR
stmfd SP!,{R1} ; Store the DFSR
mrs R1,SPSR ; Read SPSR (which is the pre-exception CPSR)
stmfd SP!,{R1} ; Store the SPSR
stmfd SP!,{LR} ; Store the link register (which is the pre-exception PC)
stmfd SP,{SP,LR}^ ; Store user/system mode stack pointer and link register
nop ; Required by ARM architecture
SUB SP,SP,#0x08 ; Adjust stack pointer
stmfd SP!,{R2-R12} ; Store general purpose registers
ldr R3,[SP,#0x50] ; Read saved R1 from the stack (it was saved by the exception entry routine)
ldr R2,[SP,#0x4C] ; Read saved R0 from the stack (it was saved by the exception entry routine)
stmfd SP!,{R2-R3} ; Store general purpose registers R0 and R1
mov R1,SP ; Prepare System Context pointer as an argument for the exception handler
sub SP,SP,#4 ; Adjust SP to preserve 8-byte alignment
blx CommonCExceptionHandler ; Call exception handler
add SP,SP,#4 ; Adjust SP back to where we were
ldr R2,[SP,#0x40] ; Load CPSR from context, in case it has changed
MSR SPSR_cxsf,R2 ; Store it back to the SPSR to be restored when exiting this handler
ldmfd SP!,{R0-R12} ; Restore general purpose registers
ldm SP,{SP,LR}^ ; Restore user/system mode stack pointer and link register
nop ; Required by ARM architecture
add SP,SP,#0x08 ; Adjust stack pointer
ldmfd SP!,{LR} ; Restore the link register (which is the pre-exception PC)
add SP,SP,#0x1C ; Clear out the remaining stack space
movs PC,LR ; Return from exception
END

View File

@@ -1,297 +1,297 @@
#------------------------------------------------------------------------------
#
# Use ARMv6 instruction to operate on a single stack
#
# Copyright (c) 2008 - 2010, Apple Inc. 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(ExceptionHandlersStart)
GCC_ASM_EXPORT(ExceptionHandlersEnd)
GCC_ASM_EXPORT(CommonExceptionEntry)
GCC_ASM_EXPORT(AsmCommonExceptionEntry)
GCC_ASM_EXPORT(CommonCExceptionHandler)
.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(ExceptionHandlersStart):
ASM_PFX(Reset):
b ASM_PFX(ResetEntry)
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(IrqEntry)
ASM_PFX(Fiq):
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
CommonCExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType, R0
IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
)
*/
blx ASM_PFX(CommonCExceptionHandler) @ 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
#------------------------------------------------------------------------------
#
# Use ARMv6 instruction to operate on a single stack
#
# Copyright (c) 2008 - 2010, Apple Inc. 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(ExceptionHandlersStart)
GCC_ASM_EXPORT(ExceptionHandlersEnd)
GCC_ASM_EXPORT(CommonExceptionEntry)
GCC_ASM_EXPORT(AsmCommonExceptionEntry)
GCC_ASM_EXPORT(CommonCExceptionHandler)
.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(ExceptionHandlersStart):
ASM_PFX(Reset):
b ASM_PFX(ResetEntry)
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(IrqEntry)
ASM_PFX(Fiq):
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
CommonCExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType, R0
IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
)
*/
blx ASM_PFX(CommonCExceptionHandler) @ 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

View File

@@ -53,7 +53,7 @@
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
[FeaturePcd]
[FeaturePcd]
gEmbeddedTokenSpaceGuid.PcdCacheEnable
[depex]

View File

@@ -1,425 +1,425 @@
/*++
Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
Portions 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.
Module Name:
Gic.c
Abstract:
Driver implementing the GIC interrupt controller protocol
--*/
#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/ArmGicLib.h>
#include <Protocol/Cpu.h>
#include <Protocol/HardwareInterrupt.h>
#define ARM_GIC_DEFAULT_PRIORITY 0x80
extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;
//
// Notifications
//
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
// Maximum Number of Interrupts
UINTN mGicNumInterrupts = 0;
HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
/**
Register Handler for the specified interrupt source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@param Handler Callback for interrupt. NULL to unregister
@retval EFI_SUCCESS Source was updated to support Handler.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
RegisterInterruptSource (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source,
IN HARDWARE_INTERRUPT_HANDLER Handler
)
{
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
return EFI_ALREADY_STARTED;
}
gRegisteredInterruptHandlers[Source] = Handler;
// If the interrupt handler is unregistered then disable the interrupt
if (NULL == Handler){
return This->DisableInterruptSource (This, Source);
} else {
return This->EnableInterruptSource (This, Source);
}
}
/**
Enable interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt enabled.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
EnableInterruptSource (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
)
{
UINT32 RegOffset;
UINTN RegShift;
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
// Calculate enable register offset and bit position
RegOffset = Source / 32;
RegShift = Source % 32;
// Write set-enable register
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset), 1 << RegShift);
return EFI_SUCCESS;
}
/**
Disable interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt disabled.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
DisableInterruptSource (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
)
{
UINT32 RegOffset;
UINTN RegShift;
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
// Calculate enable register offset and bit position
RegOffset = Source / 32;
RegShift = Source % 32;
// Write set-enable register
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDICER + (4*RegOffset), 1 << RegShift);
return EFI_SUCCESS;
}
/**
Return current state of interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@param InterruptState TRUE: source enabled, FALSE: source disabled.
@retval EFI_SUCCESS InterruptState is valid
@retval EFI_DEVICE_ERROR InterruptState is not valid
**/
EFI_STATUS
EFIAPI
GetInterruptSourceState (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source,
IN BOOLEAN *InterruptState
)
{
UINT32 RegOffset;
UINTN RegShift;
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
// calculate enable register offset and bit position
RegOffset = Source / 32;
RegShift = Source % 32;
if ((MmioRead32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset)) & (1<<RegShift)) == 0) {
*InterruptState = FALSE;
} else {
*InterruptState = TRUE;
}
return EFI_SUCCESS;
}
/**
Signal to the hardware that the End Of Intrrupt state
has been reached.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt EOI'ed.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
EndOfInterrupt (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
)
{
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCEIOR, Source);
return EFI_SUCCESS;
}
/**
EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
@param InterruptType Defines the type of interrupt or exception that
occurred on the processor.This parameter is processor architecture specific.
@param SystemContext A pointer to the processor context when
the interrupt occurred on the processor.
@return None
**/
VOID
EFIAPI
IrqInterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
UINT32 GicInterrupt;
HARDWARE_INTERRUPT_HANDLER InterruptHandler;
GicInterrupt = MmioRead32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCIAR);
// Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).
if (GicInterrupt >= mGicNumInterrupts) {
// The special interrupt do not need to be acknowledge
return;
}
InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
if (InterruptHandler != NULL) {
// Call the registered interrupt handler.
InterruptHandler (GicInterrupt, SystemContext);
} else {
DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
}
EndOfInterrupt (&gHardwareInterruptProtocol, GicInterrupt);
}
//
// Making this global saves a few bytes in image size
//
EFI_HANDLE gHardwareInterruptHandle = NULL;
//
// The protocol instance produced by this driver
//
EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {
RegisterInterruptSource,
EnableInterruptSource,
DisableInterruptSource,
GetInterruptSourceState,
EndOfInterrupt
};
/**
Shutdown our hardware
DXE Core will disable interrupts and turn off the timer and disable interrupts
after all the event handlers have run.
@param[in] Event The Event that is being processed
@param[in] Context Event Context
**/
VOID
EFIAPI
ExitBootServicesEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINTN Index;
// Acknowledge all pending interrupts
for (Index = 0; Index < mGicNumInterrupts; Index++) {
DisableInterruptSource (&gHardwareInterruptProtocol, Index);
}
for (Index = 0; Index < mGicNumInterrupts; Index++) {
EndOfInterrupt (&gHardwareInterruptProtocol, Index);
}
// Disable Gic Interface
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x0);
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0x0);
// Disable Gic Distributor
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x0);
}
/**
Initialize the state information for the CPU Architectural Protocol
@param ImageHandle of the loaded driver
@param SystemTable Pointer to the System Table
@retval EFI_SUCCESS Protocol registered
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
@retval EFI_DEVICE_ERROR Hardware problems
**/
EFI_STATUS
InterruptDxeInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINTN Index;
UINT32 RegOffset;
UINTN RegShift;
EFI_CPU_ARCH_PROTOCOL *Cpu;
UINT32 CpuTarget;
// Check PcdGicPrimaryCoreId has been set in case the Primary Core is not the core 0 of Cluster 0
DEBUG_CODE_BEGIN();
if ((PcdGet32(PcdArmPrimaryCore) != 0) && (PcdGet32 (PcdGicPrimaryCoreId) == 0)) {
DEBUG((EFI_D_WARN,"Warning: the PCD PcdGicPrimaryCoreId does not seem to be set up for the configuration.\n"));
}
DEBUG_CODE_END();
// Make sure the Interrupt Controller Protocol is not already installed in the system.
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase));
for (Index = 0; Index < mGicNumInterrupts; Index++) {
DisableInterruptSource (&gHardwareInterruptProtocol, Index);
// Set Priority
RegOffset = Index / 4;
RegShift = (Index % 4) * 8;
MmioAndThenOr32 (
PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4*RegOffset),
~(0xff << RegShift),
ARM_GIC_DEFAULT_PRIORITY << RegShift
);
}
// Configure interrupts for Primary Cpu
CpuTarget = (1 << PcdGet32 (PcdGicPrimaryCoreId));
CpuTarget |= (CpuTarget << 24) | (CpuTarget << 16) | (CpuTarget << 8);
for (Index = 0; Index < (mGicNumInterrupts / 4); Index++) {
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index*4), CpuTarget);
}
// Set binary point reg to 0x7 (no preemption)
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7);
// Set priority mask reg to 0xff to allow all priorities through
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xff);
// Enable gic cpu interface
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x1);
// Enable gic distributor
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x1);
// Initialize the array for the Interrupt Handlers
gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
Status = gBS->InstallMultipleProtocolInterfaces (
&gHardwareInterruptHandle,
&gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,
NULL
);
ASSERT_EFI_ERROR (Status);
//
// Get the CPU protocol that this driver requires.
//
Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
ASSERT_EFI_ERROR(Status);
//
// Unregister the default exception handler.
//
Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
ASSERT_EFI_ERROR(Status);
//
// Register to receive interrupts
//
Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
ASSERT_EFI_ERROR(Status);
// Register for an ExitBootServicesEvent
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
ASSERT_EFI_ERROR (Status);
return Status;
}
/*++
Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
Portions 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.
Module Name:
Gic.c
Abstract:
Driver implementing the GIC interrupt controller protocol
--*/
#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/ArmGicLib.h>
#include <Protocol/Cpu.h>
#include <Protocol/HardwareInterrupt.h>
#define ARM_GIC_DEFAULT_PRIORITY 0x80
extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol;
//
// Notifications
//
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
// Maximum Number of Interrupts
UINTN mGicNumInterrupts = 0;
HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
/**
Register Handler for the specified interrupt source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@param Handler Callback for interrupt. NULL to unregister
@retval EFI_SUCCESS Source was updated to support Handler.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
RegisterInterruptSource (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source,
IN HARDWARE_INTERRUPT_HANDLER Handler
)
{
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
return EFI_ALREADY_STARTED;
}
gRegisteredInterruptHandlers[Source] = Handler;
// If the interrupt handler is unregistered then disable the interrupt
if (NULL == Handler){
return This->DisableInterruptSource (This, Source);
} else {
return This->EnableInterruptSource (This, Source);
}
}
/**
Enable interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt enabled.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
EnableInterruptSource (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
)
{
UINT32 RegOffset;
UINTN RegShift;
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
// Calculate enable register offset and bit position
RegOffset = Source / 32;
RegShift = Source % 32;
// Write set-enable register
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset), 1 << RegShift);
return EFI_SUCCESS;
}
/**
Disable interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt disabled.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
DisableInterruptSource (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
)
{
UINT32 RegOffset;
UINTN RegShift;
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
// Calculate enable register offset and bit position
RegOffset = Source / 32;
RegShift = Source % 32;
// Write set-enable register
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDICER + (4*RegOffset), 1 << RegShift);
return EFI_SUCCESS;
}
/**
Return current state of interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@param InterruptState TRUE: source enabled, FALSE: source disabled.
@retval EFI_SUCCESS InterruptState is valid
@retval EFI_DEVICE_ERROR InterruptState is not valid
**/
EFI_STATUS
EFIAPI
GetInterruptSourceState (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source,
IN BOOLEAN *InterruptState
)
{
UINT32 RegOffset;
UINTN RegShift;
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
// calculate enable register offset and bit position
RegOffset = Source / 32;
RegShift = Source % 32;
if ((MmioRead32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDISER + (4*RegOffset)) & (1<<RegShift)) == 0) {
*InterruptState = FALSE;
} else {
*InterruptState = TRUE;
}
return EFI_SUCCESS;
}
/**
Signal to the hardware that the End Of Intrrupt state
has been reached.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt EOI'ed.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
EFI_STATUS
EFIAPI
EndOfInterrupt (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
)
{
if (Source > mGicNumInterrupts) {
ASSERT(FALSE);
return EFI_UNSUPPORTED;
}
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCEIOR, Source);
return EFI_SUCCESS;
}
/**
EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
@param InterruptType Defines the type of interrupt or exception that
occurred on the processor.This parameter is processor architecture specific.
@param SystemContext A pointer to the processor context when
the interrupt occurred on the processor.
@return None
**/
VOID
EFIAPI
IrqInterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
UINT32 GicInterrupt;
HARDWARE_INTERRUPT_HANDLER InterruptHandler;
GicInterrupt = MmioRead32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCIAR);
// Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the number of interrupt (ie: Spurious interrupt).
if (GicInterrupt >= mGicNumInterrupts) {
// The special interrupt do not need to be acknowledge
return;
}
InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
if (InterruptHandler != NULL) {
// Call the registered interrupt handler.
InterruptHandler (GicInterrupt, SystemContext);
} else {
DEBUG ((EFI_D_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
}
EndOfInterrupt (&gHardwareInterruptProtocol, GicInterrupt);
}
//
// Making this global saves a few bytes in image size
//
EFI_HANDLE gHardwareInterruptHandle = NULL;
//
// The protocol instance produced by this driver
//
EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {
RegisterInterruptSource,
EnableInterruptSource,
DisableInterruptSource,
GetInterruptSourceState,
EndOfInterrupt
};
/**
Shutdown our hardware
DXE Core will disable interrupts and turn off the timer and disable interrupts
after all the event handlers have run.
@param[in] Event The Event that is being processed
@param[in] Context Event Context
**/
VOID
EFIAPI
ExitBootServicesEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINTN Index;
// Acknowledge all pending interrupts
for (Index = 0; Index < mGicNumInterrupts; Index++) {
DisableInterruptSource (&gHardwareInterruptProtocol, Index);
}
for (Index = 0; Index < mGicNumInterrupts; Index++) {
EndOfInterrupt (&gHardwareInterruptProtocol, Index);
}
// Disable Gic Interface
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x0);
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0x0);
// Disable Gic Distributor
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x0);
}
/**
Initialize the state information for the CPU Architectural Protocol
@param ImageHandle of the loaded driver
@param SystemTable Pointer to the System Table
@retval EFI_SUCCESS Protocol registered
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
@retval EFI_DEVICE_ERROR Hardware problems
**/
EFI_STATUS
InterruptDxeInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
UINTN Index;
UINT32 RegOffset;
UINTN RegShift;
EFI_CPU_ARCH_PROTOCOL *Cpu;
UINT32 CpuTarget;
// Check PcdGicPrimaryCoreId has been set in case the Primary Core is not the core 0 of Cluster 0
DEBUG_CODE_BEGIN();
if ((PcdGet32(PcdArmPrimaryCore) != 0) && (PcdGet32 (PcdGicPrimaryCoreId) == 0)) {
DEBUG((EFI_D_WARN,"Warning: the PCD PcdGicPrimaryCoreId does not seem to be set up for the configuration.\n"));
}
DEBUG_CODE_END();
// Make sure the Interrupt Controller Protocol is not already installed in the system.
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase));
for (Index = 0; Index < mGicNumInterrupts; Index++) {
DisableInterruptSource (&gHardwareInterruptProtocol, Index);
// Set Priority
RegOffset = Index / 4;
RegShift = (Index % 4) * 8;
MmioAndThenOr32 (
PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4*RegOffset),
~(0xff << RegShift),
ARM_GIC_DEFAULT_PRIORITY << RegShift
);
}
// Configure interrupts for Primary Cpu
CpuTarget = (1 << PcdGet32 (PcdGicPrimaryCoreId));
CpuTarget |= (CpuTarget << 24) | (CpuTarget << 16) | (CpuTarget << 8);
for (Index = 0; Index < (mGicNumInterrupts / 4); Index++) {
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index*4), CpuTarget);
}
// Set binary point reg to 0x7 (no preemption)
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7);
// Set priority mask reg to 0xff to allow all priorities through
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xff);
// Enable gic cpu interface
MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x1);
// Enable gic distributor
MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x1);
// Initialize the array for the Interrupt Handlers
gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
Status = gBS->InstallMultipleProtocolInterfaces (
&gHardwareInterruptHandle,
&gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,
NULL
);
ASSERT_EFI_ERROR (Status);
//
// Get the CPU protocol that this driver requires.
//
Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
ASSERT_EFI_ERROR(Status);
//
// Unregister the default exception handler.
//
Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
ASSERT_EFI_ERROR(Status);
//
// Register to receive interrupts
//
Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
ASSERT_EFI_ERROR(Status);
// Register for an ExitBootServicesEvent
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@@ -1,57 +1,57 @@
#/** @file
#
# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
# Copyright (c) 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PL390GicDxe
FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InterruptDxeInitialize
[Sources.common]
PL390Gic.c
PL390GicDxe.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
BaseLib
UefiLib
UefiBootServicesTableLib
DebugLib
PrintLib
MemoryAllocationLib
UefiDriverEntryPoint
IoLib
[Protocols]
gHardwareInterruptProtocolGuid
gEfiCpuArchProtocolGuid
[FixedPcd.common]
gArmTokenSpaceGuid.PcdGicDistributorBase
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
gArmTokenSpaceGuid.PcdArmPrimaryCore
gArmTokenSpaceGuid.PcdGicPrimaryCoreId
[Depex]
gEfiCpuArchProtocolGuid
#/** @file
#
# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
# Copyright (c) 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PL390GicDxe
FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InterruptDxeInitialize
[Sources.common]
PL390Gic.c
PL390GicDxe.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
BaseLib
UefiLib
UefiBootServicesTableLib
DebugLib
PrintLib
MemoryAllocationLib
UefiDriverEntryPoint
IoLib
[Protocols]
gHardwareInterruptProtocolGuid
gEfiCpuArchProtocolGuid
[FixedPcd.common]
gArmTokenSpaceGuid.PcdGicDistributorBase
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
gArmTokenSpaceGuid.PcdArmPrimaryCore
gArmTokenSpaceGuid.PcdGicPrimaryCoreId
[Depex]
gEfiCpuArchProtocolGuid

View File

@@ -1,380 +1,380 @@
/** @file
Timer Architecture Protocol driver of the ARM flavor
Copyright (c) 2011 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 <PiDxe.h>
#include <Library/ArmLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/ArmV7ArchTimerLib.h>
#include <Protocol/Timer.h>
#include <Protocol/HardwareInterrupt.h>
// The notification function to call on every timer interrupt.
EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL;
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
// The current period of the timer interrupt
UINT64 mTimerPeriod = 0;
// Cached copy of the Hardware Interrupt protocol instance
EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
/**
This function registers the handler NotifyFunction so it is called every time
the timer interrupt fires. It also passes the amount of time since the last
handler call to the NotifyFunction. If NotifyFunction is NULL, then the
handler is unregistered. If the handler is registered, then EFI_SUCCESS is
returned. If the CPU does not support registering a timer interrupt handler,
then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
when a handler is already registered, then EFI_ALREADY_STARTED is returned.
If an attempt is made to unregister a handler when a handler is not registered,
then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
is returned.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@param NotifyFunction The function to call when a timer interrupt fires. This
function executes at TPL_HIGH_LEVEL. The DXE Core will
register a handler for the timer interrupt, so it can know
how much time has passed. This information is used to
signal timer based events. NULL will unregister the handler.
@retval EFI_SUCCESS The timer handler was registered.
@retval EFI_UNSUPPORTED The platform does not support timer interrupts.
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
registered.
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
previously registered.
@retval EFI_DEVICE_ERROR The timer handler could not be registered.
**/
EFI_STATUS
EFIAPI
TimerDriverRegisterHandler (
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN EFI_TIMER_NOTIFY NotifyFunction
)
{
if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
return EFI_ALREADY_STARTED;
}
mTimerNotifyFunction = NotifyFunction;
return EFI_SUCCESS;
}
/**
Disable the timer
**/
VOID
EFIAPI
ExitBootServicesEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
ArmArchTimerDisableTimer ();
}
/**
This function adjusts the period of timer interrupts to the value specified
by TimerPeriod. If the timer period is updated, then the selected timer
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
If an error occurs while attempting to update the timer period, then the
timer hardware will be put back in its state prior to this call, and
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
is disabled. This is not the same as disabling the CPU's interrupts.
Instead, it must either turn off the timer hardware, or it must adjust the
interrupt controller so that a CPU interrupt is not generated when the timer
interrupt fires.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
the timer hardware is not programmable, then EFI_UNSUPPORTED is
returned. If the timer is programmable, then the timer period
will be rounded up to the nearest timer period that is supported
by the timer hardware. If TimerPeriod is set to 0, then the
timer interrupts will be disabled.
@retval EFI_SUCCESS The timer period was changed.
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
**/
EFI_STATUS
EFIAPI
TimerDriverSetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN UINT64 TimerPeriod
)
{
UINT64 TimerTicks;
// Always disable the timer
ArmArchTimerDisableTimer ();
if (TimerPeriod != 0) {
// Convert TimerPeriod to micro sec units
TimerTicks = DivU64x32 (TimerPeriod, 10);
TimerTicks = MultU64x32 (TimerTicks, (PcdGet32(PcdArmArchTimerFreqInHz)/1000000));
ArmArchTimerSetTimerVal((UINTN)TimerTicks);
// Enable the timer
ArmArchTimerEnableTimer ();
}
// Save the new timer period
mTimerPeriod = TimerPeriod;
return EFI_SUCCESS;
}
/**
This function retrieves the period of timer interrupts in 100 ns units,
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
returned, then the timer is currently disabled.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
0 is returned, then the timer is currently disabled.
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
**/
EFI_STATUS
EFIAPI
TimerDriverGetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
OUT UINT64 *TimerPeriod
)
{
if (TimerPeriod == NULL) {
return EFI_INVALID_PARAMETER;
}
*TimerPeriod = mTimerPeriod;
return EFI_SUCCESS;
}
/**
This function generates a soft timer interrupt. If the platform does not support soft
timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
service, then a soft timer interrupt will be generated. If the timer interrupt is
enabled when this service is called, then the registered handler will be invoked. The
registered handler should not be able to distinguish a hardware-generated timer
interrupt from a software-generated timer interrupt.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@retval EFI_SUCCESS The soft timer interrupt was generated.
@retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts.
**/
EFI_STATUS
EFIAPI
TimerDriverGenerateSoftInterrupt (
IN EFI_TIMER_ARCH_PROTOCOL *This
)
{
return EFI_UNSUPPORTED;
}
/**
Interface structure for the Timer Architectural Protocol.
@par Protocol Description:
This protocol provides the services to initialize a periodic timer
interrupt, and to register a handler that is called each time the timer
interrupt fires. It may also provide a service to adjust the rate of the
periodic timer interrupt. When a timer interrupt occurs, the handler is
passed the amount of time that has passed since the previous timer
interrupt.
@param RegisterHandler
Registers a handler that will be called each time the
timer interrupt fires. TimerPeriod defines the minimum
time between timer interrupts, so TimerPeriod will also
be the minimum time between calls to the registered
handler.
@param SetTimerPeriod
Sets the period of the timer interrupt in 100 nS units.
This function is optional, and may return EFI_UNSUPPORTED.
If this function is supported, then the timer period will
be rounded up to the nearest supported timer period.
@param GetTimerPeriod
Retrieves the period of the timer interrupt in 100 nS units.
@param GenerateSoftInterrupt
Generates a soft timer interrupt that simulates the firing of
the timer interrupt. This service can be used to invoke the registered handler if the timer interrupt has been masked for
a period of time.
**/
EFI_TIMER_ARCH_PROTOCOL gTimer = {
TimerDriverRegisterHandler,
TimerDriverSetTimerPeriod,
TimerDriverGetTimerPeriod,
TimerDriverGenerateSoftInterrupt
};
/**
C Interrupt Handler called in the interrupt context when Source interrupt is active.
@param Source Source of the interrupt. Hardware routing off a specific platform defines
what source means.
@param SystemContext Pointer to system register context. Mostly used by debuggers and will
update the system context after the return from the interrupt if
modified. Don't change these values unless you know what you are doing
**/
VOID
EFIAPI
TimerInterruptHandler (
IN HARDWARE_INTERRUPT_SOURCE Source,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
EFI_TPL OriginalTPL;
//
// DXE core uses this callback for the EFI timer tick. The DXE core uses locks
// that raise to TPL_HIGH and then restore back to current level. Thus we need
// to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
//
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
// Check if the timer interrupt is active
if ((ArmArchTimerGetTimerCtrlReg () ) & ARM_ARCH_TIMER_ISTATUS) {
// Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers
gInterrupt->EndOfInterrupt (gInterrupt, Source);
if (mTimerNotifyFunction) {
mTimerNotifyFunction (mTimerPeriod);
}
// Reload the Timer
TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
}
// Enable timer interrupts
gInterrupt->EnableInterruptSource (gInterrupt, Source);
gBS->RestoreTPL (OriginalTPL);
}
/**
Initialize the state information for the Timer Architectural Protocol and
the Timer Debug support protocol that allows the debugger to break into a
running program.
@param ImageHandle of the loaded driver
@param SystemTable Pointer to the System Table
@retval EFI_SUCCESS Protocol registered
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
@retval EFI_DEVICE_ERROR Hardware problems
**/
EFI_STATUS
EFIAPI
TimerInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_HANDLE Handle = NULL;
EFI_STATUS Status;
UINTN TimerCtrlReg;
if (ArmIsArchTimerImplemented () == 0) {
DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence cann't use this Driver \n"));
ASSERT (0);
}
// Find the interrupt controller protocol. ASSERT if not found.
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
ASSERT_EFI_ERROR (Status);
// Disable the timer
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
ASSERT_EFI_ERROR (Status);
// Install secure and Non-secure interrupt handlers
// Note: Because it is not possible to determine the security state of the
// CPU dynamically, we just install interrupt handler for both sec and non-sec
// timer PPI
Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum), TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
// Unmask timer interrupts
TimerCtrlReg = ArmArchTimerGetTimerCtrlReg ();
TimerCtrlReg &= ~ARM_ARCH_TIMER_IMASK;
ArmArchTimerSetTimerCtrlReg (TimerCtrlReg);
// Set up default timer
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD
ASSERT_EFI_ERROR (Status);
// Install the Timer Architectural Protocol onto a new handle
Status = gBS->InstallMultipleProtocolInterfaces(
&Handle,
&gEfiTimerArchProtocolGuid, &gTimer,
NULL
);
ASSERT_EFI_ERROR(Status);
// enable Secure timer interrupts
Status = gInterrupt->EnableInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum));
// enable NonSecure timer interrupts
Status = gInterrupt->EnableInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum));
// Register for an ExitBootServicesEvent
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
ASSERT_EFI_ERROR (Status);
return Status;
}
/** @file
Timer Architecture Protocol driver of the ARM flavor
Copyright (c) 2011 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 <PiDxe.h>
#include <Library/ArmLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/ArmV7ArchTimerLib.h>
#include <Protocol/Timer.h>
#include <Protocol/HardwareInterrupt.h>
// The notification function to call on every timer interrupt.
EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL;
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
// The current period of the timer interrupt
UINT64 mTimerPeriod = 0;
// Cached copy of the Hardware Interrupt protocol instance
EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
/**
This function registers the handler NotifyFunction so it is called every time
the timer interrupt fires. It also passes the amount of time since the last
handler call to the NotifyFunction. If NotifyFunction is NULL, then the
handler is unregistered. If the handler is registered, then EFI_SUCCESS is
returned. If the CPU does not support registering a timer interrupt handler,
then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
when a handler is already registered, then EFI_ALREADY_STARTED is returned.
If an attempt is made to unregister a handler when a handler is not registered,
then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
is returned.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@param NotifyFunction The function to call when a timer interrupt fires. This
function executes at TPL_HIGH_LEVEL. The DXE Core will
register a handler for the timer interrupt, so it can know
how much time has passed. This information is used to
signal timer based events. NULL will unregister the handler.
@retval EFI_SUCCESS The timer handler was registered.
@retval EFI_UNSUPPORTED The platform does not support timer interrupts.
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
registered.
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
previously registered.
@retval EFI_DEVICE_ERROR The timer handler could not be registered.
**/
EFI_STATUS
EFIAPI
TimerDriverRegisterHandler (
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN EFI_TIMER_NOTIFY NotifyFunction
)
{
if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
return EFI_ALREADY_STARTED;
}
mTimerNotifyFunction = NotifyFunction;
return EFI_SUCCESS;
}
/**
Disable the timer
**/
VOID
EFIAPI
ExitBootServicesEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
ArmArchTimerDisableTimer ();
}
/**
This function adjusts the period of timer interrupts to the value specified
by TimerPeriod. If the timer period is updated, then the selected timer
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
If an error occurs while attempting to update the timer period, then the
timer hardware will be put back in its state prior to this call, and
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
is disabled. This is not the same as disabling the CPU's interrupts.
Instead, it must either turn off the timer hardware, or it must adjust the
interrupt controller so that a CPU interrupt is not generated when the timer
interrupt fires.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
the timer hardware is not programmable, then EFI_UNSUPPORTED is
returned. If the timer is programmable, then the timer period
will be rounded up to the nearest timer period that is supported
by the timer hardware. If TimerPeriod is set to 0, then the
timer interrupts will be disabled.
@retval EFI_SUCCESS The timer period was changed.
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
**/
EFI_STATUS
EFIAPI
TimerDriverSetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
IN UINT64 TimerPeriod
)
{
UINT64 TimerTicks;
// Always disable the timer
ArmArchTimerDisableTimer ();
if (TimerPeriod != 0) {
// Convert TimerPeriod to micro sec units
TimerTicks = DivU64x32 (TimerPeriod, 10);
TimerTicks = MultU64x32 (TimerTicks, (PcdGet32(PcdArmArchTimerFreqInHz)/1000000));
ArmArchTimerSetTimerVal((UINTN)TimerTicks);
// Enable the timer
ArmArchTimerEnableTimer ();
}
// Save the new timer period
mTimerPeriod = TimerPeriod;
return EFI_SUCCESS;
}
/**
This function retrieves the period of timer interrupts in 100 ns units,
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
returned, then the timer is currently disabled.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
0 is returned, then the timer is currently disabled.
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
**/
EFI_STATUS
EFIAPI
TimerDriverGetTimerPeriod (
IN EFI_TIMER_ARCH_PROTOCOL *This,
OUT UINT64 *TimerPeriod
)
{
if (TimerPeriod == NULL) {
return EFI_INVALID_PARAMETER;
}
*TimerPeriod = mTimerPeriod;
return EFI_SUCCESS;
}
/**
This function generates a soft timer interrupt. If the platform does not support soft
timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
service, then a soft timer interrupt will be generated. If the timer interrupt is
enabled when this service is called, then the registered handler will be invoked. The
registered handler should not be able to distinguish a hardware-generated timer
interrupt from a software-generated timer interrupt.
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
@retval EFI_SUCCESS The soft timer interrupt was generated.
@retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts.
**/
EFI_STATUS
EFIAPI
TimerDriverGenerateSoftInterrupt (
IN EFI_TIMER_ARCH_PROTOCOL *This
)
{
return EFI_UNSUPPORTED;
}
/**
Interface structure for the Timer Architectural Protocol.
@par Protocol Description:
This protocol provides the services to initialize a periodic timer
interrupt, and to register a handler that is called each time the timer
interrupt fires. It may also provide a service to adjust the rate of the
periodic timer interrupt. When a timer interrupt occurs, the handler is
passed the amount of time that has passed since the previous timer
interrupt.
@param RegisterHandler
Registers a handler that will be called each time the
timer interrupt fires. TimerPeriod defines the minimum
time between timer interrupts, so TimerPeriod will also
be the minimum time between calls to the registered
handler.
@param SetTimerPeriod
Sets the period of the timer interrupt in 100 nS units.
This function is optional, and may return EFI_UNSUPPORTED.
If this function is supported, then the timer period will
be rounded up to the nearest supported timer period.
@param GetTimerPeriod
Retrieves the period of the timer interrupt in 100 nS units.
@param GenerateSoftInterrupt
Generates a soft timer interrupt that simulates the firing of
the timer interrupt. This service can be used to invoke the registered handler if the timer interrupt has been masked for
a period of time.
**/
EFI_TIMER_ARCH_PROTOCOL gTimer = {
TimerDriverRegisterHandler,
TimerDriverSetTimerPeriod,
TimerDriverGetTimerPeriod,
TimerDriverGenerateSoftInterrupt
};
/**
C Interrupt Handler called in the interrupt context when Source interrupt is active.
@param Source Source of the interrupt. Hardware routing off a specific platform defines
what source means.
@param SystemContext Pointer to system register context. Mostly used by debuggers and will
update the system context after the return from the interrupt if
modified. Don't change these values unless you know what you are doing
**/
VOID
EFIAPI
TimerInterruptHandler (
IN HARDWARE_INTERRUPT_SOURCE Source,
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
EFI_TPL OriginalTPL;
//
// DXE core uses this callback for the EFI timer tick. The DXE core uses locks
// that raise to TPL_HIGH and then restore back to current level. Thus we need
// to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
//
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
// Check if the timer interrupt is active
if ((ArmArchTimerGetTimerCtrlReg () ) & ARM_ARCH_TIMER_ISTATUS) {
// Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers
gInterrupt->EndOfInterrupt (gInterrupt, Source);
if (mTimerNotifyFunction) {
mTimerNotifyFunction (mTimerPeriod);
}
// Reload the Timer
TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod));
}
// Enable timer interrupts
gInterrupt->EnableInterruptSource (gInterrupt, Source);
gBS->RestoreTPL (OriginalTPL);
}
/**
Initialize the state information for the Timer Architectural Protocol and
the Timer Debug support protocol that allows the debugger to break into a
running program.
@param ImageHandle of the loaded driver
@param SystemTable Pointer to the System Table
@retval EFI_SUCCESS Protocol registered
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
@retval EFI_DEVICE_ERROR Hardware problems
**/
EFI_STATUS
EFIAPI
TimerInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_HANDLE Handle = NULL;
EFI_STATUS Status;
UINTN TimerCtrlReg;
if (ArmIsArchTimerImplemented () == 0) {
DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence cann't use this Driver \n"));
ASSERT (0);
}
// Find the interrupt controller protocol. ASSERT if not found.
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
ASSERT_EFI_ERROR (Status);
// Disable the timer
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
ASSERT_EFI_ERROR (Status);
// Install secure and Non-secure interrupt handlers
// Note: Because it is not possible to determine the security state of the
// CPU dynamically, we just install interrupt handler for both sec and non-sec
// timer PPI
Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum), TimerInterruptHandler);
ASSERT_EFI_ERROR (Status);
// Unmask timer interrupts
TimerCtrlReg = ArmArchTimerGetTimerCtrlReg ();
TimerCtrlReg &= ~ARM_ARCH_TIMER_IMASK;
ArmArchTimerSetTimerCtrlReg (TimerCtrlReg);
// Set up default timer
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD
ASSERT_EFI_ERROR (Status);
// Install the Timer Architectural Protocol onto a new handle
Status = gBS->InstallMultipleProtocolInterfaces(
&Handle,
&gEfiTimerArchProtocolGuid, &gTimer,
NULL
);
ASSERT_EFI_ERROR(Status);
// enable Secure timer interrupts
Status = gInterrupt->EnableInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum));
// enable NonSecure timer interrupts
Status = gInterrupt->EnableInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum));
// Register for an ExitBootServicesEvent
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@@ -1,59 +1,59 @@
#/** @file
#
# Component description file for Timer DXE module
#
# Copyright (c) 2009 - 2010, Apple Inc. 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = ArmTimerDxe
FILE_GUID = 49ea041e-6752-42ca-b0b1-7344fe2546b7
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = TimerInitialize
[Sources.common]
TimerDxe.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
[LibraryClasses]
ArmLib
BaseLib
UefiRuntimeServicesTableLib
UefiLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
UefiDriverEntryPoint
IoLib
[Guids]
[Protocols]
gEfiTimerArchProtocolGuid
gHardwareInterruptProtocolGuid
[Pcd.common]
gEmbeddedTokenSpaceGuid.PcdTimerPeriod
gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
[Depex]
gHardwareInterruptProtocolGuid
#/** @file
#
# Component description file for Timer DXE module
#
# Copyright (c) 2009 - 2010, Apple Inc. 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = ArmTimerDxe
FILE_GUID = 49ea041e-6752-42ca-b0b1-7344fe2546b7
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = TimerInitialize
[Sources.common]
TimerDxe.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPkg/ArmPkg.dec
ArmPlatformPkg/ArmPlatformPkg.dec
[LibraryClasses]
ArmLib
BaseLib
UefiRuntimeServicesTableLib
UefiLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
UefiDriverEntryPoint
IoLib
[Guids]
[Protocols]
gEfiTimerArchProtocolGuid
gHardwareInterruptProtocolGuid
[Pcd.common]
gEmbeddedTokenSpaceGuid.PcdTimerPeriod
gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
[Depex]
gHardwareInterruptProtocolGuid