summaryrefslogtreecommitdiffstats
path: root/EmbeddedPkg/TemplateCpuDxe
diff options
context:
space:
mode:
Diffstat (limited to 'EmbeddedPkg/TemplateCpuDxe')
-rw-r--r--EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c250
-rwxr-xr-xEmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S158
-rwxr-xr-xEmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm152
-rw-r--r--EmbeddedPkg/TemplateCpuDxe/CpuDxe.c323
-rw-r--r--EmbeddedPkg/TemplateCpuDxe/CpuDxe.h124
-rw-r--r--EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c183
-rw-r--r--EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf71
-rw-r--r--EmbeddedPkg/TemplateCpuDxe/X64/Exception.c183
8 files changed, 1444 insertions, 0 deletions
diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c b/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c
new file mode 100644
index 0000000000..e32d47e123
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c
@@ -0,0 +1,250 @@
+/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <CpuDxe.h>
+#include <Library/CacheMaintenanceLib.h>
+
+VOID
+ExceptionHandlersStart (
+ VOID
+ );
+
+VOID
+ExceptionHandlersEnd (
+ VOID
+ );
+
+VOID
+CommonExceptionEntry (
+ VOID
+ );
+
+VOID
+AsmCommonExceptionEntry (
+ VOID
+ );
+
+
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType > MAX_ARM_EXCEPTION) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+VOID
+EFIAPI
+DefaultSWIExceptionHandler(
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ return;
+}
+
+
+VOID
+EFIAPI
+DefaultExceptionHandler(
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextArm->PC));
+ ASSERT (FALSE);
+
+ return;
+}
+
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Offset;
+ UINTN Length;
+ UINTN Index;
+ BOOLEAN Enabled;
+
+ //
+ // Disable interrupts
+ //
+ Cpu->GetInterruptState (Cpu, &Enabled);
+ Cpu->DisableInterrupt (Cpu);
+
+ //
+ // Initialize the C entry points for interrupts
+ //
+ for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
+ if (Index == EXCEPT_ARM_SOFTWARE_INTERRUPT) {
+ Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultSWIExceptionHandler);
+ } else {
+ Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultExceptionHandler);
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Copy an implementation of the ARM exception vectors to 0x0.
+ //
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
+
+ CopyMem ((VOID *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress), (VOID *)ExceptionHandlersStart, Length);
+
+ //
+ // Patch in the common Assembly exception handler
+ //
+ Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
+ *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
+
+ //
+ // Flush Caches since we updated executable stuff
+ //
+ InvalidateInstructionCache ();
+
+ if (Enabled) {
+ //
+ // Restore interrupt state
+ //
+ Status = Cpu->EnableInterrupt (Cpu);
+ }
+
+ return Status;
+}
+
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeWriteBack) {
+ WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S
new file mode 100755
index 0000000000..d864759afd
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S
@@ -0,0 +1,158 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#------------------------------------------------------------------------------
+
+.text
+.align 2
+
+.globl _ExceptionHandlersStart
+.globl _ExceptionHandlersEnd
+.globl _CommonExceptionEntry
+.globl _AsmCommonExceptionEntry
+.globl _gExceptionHandlers
+
+_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:
+ .byte 0x12
+ .byte 0x34
+ .byte 0x56
+ .byte 0x78
+
+_ExceptionHandlersEnd:
+
+LIndirectgExceptionHandlers:
+ .long _gExceptionHandlers
+
+_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,#0x40] @ Read saved R1 from the stack (it was saved by the exception entry routine)
+ ldr r2,[sp,#0x3C] @ 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
+
+ ldr r2,LIndirectgExceptionHandlers @ Offset to 32-bit address of exception handler
+ ldr r2,[r2] @ Load exception handler table
+ ldr r3,[r2,r0,lsl #2] @ Index to find the handler for this exception
+
+// blx r3 @ Call exception handler
+ bx r3 @ Call exception handler
+
+ 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
+ ldmia 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
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm
new file mode 100755
index 0000000000..b91639d149
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm
@@ -0,0 +1,152 @@
+//------------------------------------------------------------------------------
+//
+// Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+//
+// All rights reserved. This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+//------------------------------------------------------------------------------
+
+ EXPORT ExceptionHandlersStart
+ EXPORT ExceptionHandlersEnd
+ EXPORT CommonExceptionEntry
+ EXPORT AsmCommonExceptionEntry
+ IMPORT gExceptionHandlers
+
+ 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,#0x40] ; Read saved R1 from the stack (it was saved by the exception entry routine)
+ LDR R2,[SP,#0x3C] ; 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
+
+ LDR R2,=gExceptionHandlers ; Load exception handler table
+ LDR R3,[R2,R0,LSL #2] ; Index to find the handler for this exception
+
+ BLX R3 ; Call exception handler
+
+ 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
+
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c
new file mode 100644
index 0000000000..90bf8a9af8
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c
@@ -0,0 +1,323 @@
+/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CpuDxe.h"
+
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ return FlushCpuDataCache (Start, Length, FlushType);
+}
+
+
+/**
+ This function enables interrupt processing by the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are enabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ EnableInterrupts ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function disables interrupt processing by the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are disabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+ Disables CPU interrupts.
+
+Arguments:
+ This - Protocol instance structure
+
+Returns:
+ EFI_SUCCESS - If interrupts were disabled in the CPU.
+ EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.
+
+--*/
+{
+ DisableInterrupts ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function retrieves the processor's current interrupt state a returns it in
+ State. If interrupts are currently enabled, then TRUE is returned. If interrupts
+ are currently disabled, then FALSE is returned.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param State A pointer to the processor's current interrupt state. Set to TRUE if
+ interrupts are enabled and FALSE if interrupts are disabled.
+
+ @retval EFI_SUCCESS The processor's current interrupt state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = GetInterruptState ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function generates an INIT on the processor. If this function succeeds, then the
+ processor will be reset, and control will not be returned to the caller. If InitType is
+ not supported by this processor, or the processor cannot programmatically generate an
+ INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
+ occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InitType The type of processor INIT to perform.
+
+ @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
+ @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
+ by this processor.
+ @retval EFI_DEVICE_ERROR The processor INIT failed.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ return RegisterInterruptHandler (InterruptType, InterruptHandler);
+}
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ return GetTimerValue (TimerIndex, TimerValue, TimerPeriod);
+}
+
+
+/**
+ This function modifies the attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ //
+ // This is used to set cachability via the MMU on ARM
+ //
+ // This more about optimization and we can usually run fine if the default
+ // settings for cachability are good.
+ //
+ return EFI_UNSUPPORTED;
+}
+
+
+
+
+//
+// Globals used to initialize the protocol
+//
+EFI_HANDLE mCpuHandle = NULL;
+EFI_CPU_ARCH_PROTOCOL mCpu = {
+ CpuFlushCpuDataCache,
+ CpuEnableInterrupt,
+ CpuDisableInterrupt,
+ CpuGetInterruptState,
+ CpuInit,
+ CpuRegisterInterruptHandler,
+ CpuGetTimerValue,
+ CpuSetMemoryAttributes,
+ 0, // NumberOfTimers
+ 4, // DmaBufferAlignment
+};
+
+
+/**
+ 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
+CpuDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ InitializeExceptions (&mCpu);
+
+ //
+ // Install CPU Architectural Protocol and the thunk protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mCpuHandle,
+ &gEfiCpuArchProtocolGuid, &mCpu,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h
new file mode 100644
index 0000000000..c81d8012f8
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h
@@ -0,0 +1,124 @@
+/** @file
+
+ Copyright (c) 2006 - 2008, Intel Corporation <BR>
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/DebugSupport.h>
+
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ );
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c b/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c
new file mode 100644
index 0000000000..5ba38e1623
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c
@@ -0,0 +1,183 @@
+/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <CpuDxe.h>
+
+
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType > 0xFF) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+VOID
+EFIAPI
+DefaultExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextIa32->Eip));
+ ASSERT (FALSE);
+
+ return;
+}
+
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ )
+{
+ // You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
+ // and write all the assembly to handle the interrupts.
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex == 0) {
+ *TimerValue = AsmReadTsc ();
+ if (TimerPeriod != NULL) {
+ //
+ // BugBug: Hard coded. Don't know how to do this generically
+ //
+ *TimerPeriod = 1000000000;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf b/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf
new file mode 100644
index 0000000000..67d3edc7c4
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf
@@ -0,0 +1,71 @@
+#%HEADER%
+#/** @file
+#
+# Component discription file for Bds module
+#
+# Copyright (c) 2008, Intel Corporation. <BR>
+# 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 = TemplateCpuDxe
+ FILE_GUID = CB6DC1E4-5B27-41E8-BC27-9AA50B62081E
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = CpuDxeInitialize
+
+
+[Sources.common]
+ CpuDxe.c
+
+[Sources.ARM]
+ Arm/Exception.c
+ Arm/Exceptions.asm
+ Arm/Exceptions.S
+
+[Sources.IA32]
+ IA32/Exception.c
+
+[Sources.X64]
+ X64/Exception.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[Packages.ARM]
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ PerformanceLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ UefiDriverEntryPoint
+ CacheMaintenanceLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[Pcd.ARM]
+ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
+
+
+[depex]
+ TRUE
diff --git a/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c b/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c
new file mode 100644
index 0000000000..f86eda077a
--- /dev/null
+++ b/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c
@@ -0,0 +1,183 @@
+/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <CpuDxe.h>
+
+
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType > 0xFF) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+VOID
+EFIAPI
+DefaultExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextX64->Rip));
+ ASSERT (FALSE);
+
+ return;
+}
+
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ )
+{
+ // You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
+ // and write all the assembly to handle the interrupts.
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex == 0) {
+ *TimerValue = AsmReadTsc ();
+ if (TimerPeriod != NULL) {
+ //
+ // BugBug: Hard coded. Don't know how to do this generically
+ //
+ *TimerPeriod = 1000000000;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+
+