Adding support for BeagleBoard.
ArmPkg - Supoprt for ARM specific things that can change as the architecture changes. Plus semihosting JTAG drivers. EmbeddedPkg - Generic support for an embeddded platform. Including a light weight command line shell. BeagleBoardPkg - Platform specifics for BeagleBoard. SD Card works, but USB has issues. Looks like a bug in the open source USB stack (Our internal stack works fine). git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9518 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
250
EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c
Normal file
250
EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
158
EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S
Executable file
158
EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S
Executable file
@@ -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
|
||||
|
152
EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm
Executable file
152
EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm
Executable file
@@ -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
|
||||
|
||||
|
323
EmbeddedPkg/TemplateCpuDxe/CpuDxe.c
Normal file
323
EmbeddedPkg/TemplateCpuDxe/CpuDxe.c
Normal file
@@ -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;
|
||||
}
|
||||
|
124
EmbeddedPkg/TemplateCpuDxe/CpuDxe.h
Normal file
124
EmbeddedPkg/TemplateCpuDxe/CpuDxe.h
Normal file
@@ -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
|
||||
);
|
||||
|
||||
|
183
EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c
Normal file
183
EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
71
EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf
Normal file
71
EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf
Normal file
@@ -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
|
183
EmbeddedPkg/TemplateCpuDxe/X64/Exception.c
Normal file
183
EmbeddedPkg/TemplateCpuDxe/X64/Exception.c
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user