diff options
Diffstat (limited to 'roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib')
4 files changed, 664 insertions, 0 deletions
diff --git a/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c new file mode 100644 index 000000000..ba3c0e0cc --- /dev/null +++ b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c @@ -0,0 +1,275 @@ +/** @file
+ Default exception handler
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ArmDisassemblerLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Guid/DebugImageInfoTable.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/LoadedImage.h>
+
+STATIC CHAR8 *gExceptionTypeString[] = {
+ "Synchronous",
+ "IRQ",
+ "FIQ",
+ "SError"
+};
+
+STATIC BOOLEAN mRecursiveException;
+
+CHAR8 *
+GetImageName (
+ IN UINTN FaultAddress,
+ OUT UINTN *ImageBase,
+ OUT UINTN *PeCoffSizeOfHeaders
+ );
+
+STATIC
+VOID
+DescribeInstructionOrDataAbort (
+ IN CHAR8 *AbortType,
+ IN UINTN Iss
+ )
+{
+ CHAR8 *AbortCause;
+
+ switch (Iss & 0x3f) {
+ case 0x0: AbortCause = "Address size fault, zeroth level of translation or translation table base register"; break;
+ case 0x1: AbortCause = "Address size fault, first level"; break;
+ case 0x2: AbortCause = "Address size fault, second level"; break;
+ case 0x3: AbortCause = "Address size fault, third level"; break;
+ case 0x4: AbortCause = "Translation fault, zeroth level"; break;
+ case 0x5: AbortCause = "Translation fault, first level"; break;
+ case 0x6: AbortCause = "Translation fault, second level"; break;
+ case 0x7: AbortCause = "Translation fault, third level"; break;
+ case 0x9: AbortCause = "Access flag fault, first level"; break;
+ case 0xa: AbortCause = "Access flag fault, second level"; break;
+ case 0xb: AbortCause = "Access flag fault, third level"; break;
+ case 0xd: AbortCause = "Permission fault, first level"; break;
+ case 0xe: AbortCause = "Permission fault, second level"; break;
+ case 0xf: AbortCause = "Permission fault, third level"; break;
+ case 0x10: AbortCause = "Synchronous external abort"; break;
+ case 0x18: AbortCause = "Synchronous parity error on memory access"; break;
+ case 0x11: AbortCause = "Asynchronous external abort"; break;
+ case 0x19: AbortCause = "Asynchronous parity error on memory access"; break;
+ case 0x14: AbortCause = "Synchronous external abort on translation table walk, zeroth level"; break;
+ case 0x15: AbortCause = "Synchronous external abort on translation table walk, first level"; break;
+ case 0x16: AbortCause = "Synchronous external abort on translation table walk, second level"; break;
+ case 0x17: AbortCause = "Synchronous external abort on translation table walk, third level"; break;
+ case 0x1c: AbortCause = "Synchronous parity error on memory access on translation table walk, zeroth level"; break;
+ case 0x1d: AbortCause = "Synchronous parity error on memory access on translation table walk, first level"; break;
+ case 0x1e: AbortCause = "Synchronous parity error on memory access on translation table walk, second level"; break;
+ case 0x1f: AbortCause = "Synchronous parity error on memory access on translation table walk, third level"; break;
+ case 0x21: AbortCause = "Alignment fault"; break;
+ case 0x22: AbortCause = "Debug event"; break;
+ case 0x30: AbortCause = "TLB conflict abort"; break;
+ case 0x33:
+ case 0x34: AbortCause = "IMPLEMENTATION DEFINED"; break;
+ case 0x35:
+ case 0x36: AbortCause = "Domain fault"; break;
+ default: AbortCause = ""; break;
+ }
+
+ DEBUG ((EFI_D_ERROR, "\n%a: %a\n", AbortType, AbortCause));
+}
+
+STATIC
+VOID
+DescribeExceptionSyndrome (
+ IN UINT32 Esr
+ )
+{
+ CHAR8 *Message;
+ UINTN Ec;
+ UINTN Iss;
+
+ Ec = Esr >> 26;
+ Iss = Esr & 0x00ffffff;
+
+ switch (Ec) {
+ case 0x15: Message = "SVC executed in AArch64"; break;
+ case 0x20:
+ case 0x21: DescribeInstructionOrDataAbort ("Instruction abort", Iss); return;
+ case 0x22: Message = "PC alignment fault"; break;
+ case 0x23: Message = "SP alignment fault"; break;
+ case 0x24:
+ case 0x25: DescribeInstructionOrDataAbort ("Data abort", Iss); return;
+ default: return;
+ }
+
+ DEBUG ((EFI_D_ERROR, "\n %a \n", Message));
+}
+
+#ifndef MDEPKG_NDEBUG
+STATIC
+CONST CHAR8 *
+BaseName (
+ IN CONST CHAR8 *FullName
+ )
+{
+ CONST CHAR8 *Str;
+
+ Str = FullName + AsciiStrLen (FullName);
+
+ while (--Str > FullName) {
+ if (*Str == '/' || *Str == '\\') {
+ return Str + 1;
+ }
+ }
+ return Str;
+}
+#endif
+
+/**
+ This is the default action to take on an unexpected exception
+
+ Since this is exception context don't do anything crazy like try to allocate memory.
+
+ @param ExceptionType Type of the exception
+ @param SystemContext Register state at the time of the Exception
+
+**/
+VOID
+DefaultExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+ INT32 Offset;
+
+ if (mRecursiveException) {
+ STATIC CHAR8 CONST Message[] = "\nRecursive exception occurred while dumping the CPU state\n";
+
+ SerialPortWrite ((UINT8 *)Message, sizeof Message - 1);
+ if (gST->ConOut != NULL) {
+ AsciiPrint (Message);
+ }
+ CpuDeadLoop ();
+ }
+ mRecursiveException = TRUE;
+
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"\n\n%a Exception at 0x%016lx\n", gExceptionTypeString[ExceptionType], SystemContext.SystemContextAArch64->ELR);
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);
+ if (gST->ConOut != NULL) {
+ AsciiPrint (Buffer);
+ }
+
+ DEBUG_CODE_BEGIN ();
+ CHAR8 *Pdb, *PrevPdb;
+ UINTN ImageBase;
+ UINTN PeCoffSizeOfHeader;
+ UINT64 *Fp;
+ UINT64 RootFp[2];
+ UINTN Idx;
+
+ PrevPdb = Pdb = GetImageName (SystemContext.SystemContextAArch64->ELR, &ImageBase, &PeCoffSizeOfHeader);
+ if (Pdb != NULL) {
+ DEBUG ((EFI_D_ERROR, "PC 0x%012lx (0x%012lx+0x%08x) [ 0] %a\n",
+ SystemContext.SystemContextAArch64->ELR, ImageBase,
+ SystemContext.SystemContextAArch64->ELR - ImageBase, BaseName (Pdb)));
+ } else {
+ DEBUG ((EFI_D_ERROR, "PC 0x%012lx\n", SystemContext.SystemContextAArch64->ELR));
+ }
+
+ if ((UINT64 *)SystemContext.SystemContextAArch64->FP != 0) {
+ Idx = 0;
+
+ RootFp[0] = ((UINT64 *)SystemContext.SystemContextAArch64->FP)[0];
+ RootFp[1] = ((UINT64 *)SystemContext.SystemContextAArch64->FP)[1];
+ if (RootFp[1] != SystemContext.SystemContextAArch64->LR) {
+ RootFp[0] = SystemContext.SystemContextAArch64->FP;
+ RootFp[1] = SystemContext.SystemContextAArch64->LR;
+ }
+ for (Fp = RootFp; Fp[0] != 0; Fp = (UINT64 *)Fp[0]) {
+ Pdb = GetImageName (Fp[1], &ImageBase, &PeCoffSizeOfHeader);
+ if (Pdb != NULL) {
+ if (Pdb != PrevPdb) {
+ Idx++;
+ PrevPdb = Pdb;
+ }
+ DEBUG ((EFI_D_ERROR, "PC 0x%012lx (0x%012lx+0x%08x) [% 2d] %a\n",
+ Fp[1], ImageBase, Fp[1] - ImageBase, Idx, BaseName (Pdb)));
+ } else {
+ DEBUG ((EFI_D_ERROR, "PC 0x%012lx\n", Fp[1]));
+ }
+ }
+ PrevPdb = Pdb = GetImageName (SystemContext.SystemContextAArch64->ELR, &ImageBase, &PeCoffSizeOfHeader);
+ if (Pdb != NULL) {
+ DEBUG ((EFI_D_ERROR, "\n[ 0] %a\n", Pdb));
+ }
+
+ Idx = 0;
+ for (Fp = RootFp; Fp[0] != 0; Fp = (UINT64 *)Fp[0]) {
+ Pdb = GetImageName (Fp[1], &ImageBase, &PeCoffSizeOfHeader);
+ if (Pdb != NULL && Pdb != PrevPdb) {
+ DEBUG ((EFI_D_ERROR, "[% 2d] %a\n", ++Idx, Pdb));
+ PrevPdb = Pdb;
+ }
+ }
+ }
+ DEBUG_CODE_END ();
+
+ DEBUG ((EFI_D_ERROR, "\n X0 0x%016lx X1 0x%016lx X2 0x%016lx X3 0x%016lx\n", SystemContext.SystemContextAArch64->X0, SystemContext.SystemContextAArch64->X1, SystemContext.SystemContextAArch64->X2, SystemContext.SystemContextAArch64->X3));
+ DEBUG ((EFI_D_ERROR, " X4 0x%016lx X5 0x%016lx X6 0x%016lx X7 0x%016lx\n", SystemContext.SystemContextAArch64->X4, SystemContext.SystemContextAArch64->X5, SystemContext.SystemContextAArch64->X6, SystemContext.SystemContextAArch64->X7));
+ DEBUG ((EFI_D_ERROR, " X8 0x%016lx X9 0x%016lx X10 0x%016lx X11 0x%016lx\n", SystemContext.SystemContextAArch64->X8, SystemContext.SystemContextAArch64->X9, SystemContext.SystemContextAArch64->X10, SystemContext.SystemContextAArch64->X11));
+ DEBUG ((EFI_D_ERROR, " X12 0x%016lx X13 0x%016lx X14 0x%016lx X15 0x%016lx\n", SystemContext.SystemContextAArch64->X12, SystemContext.SystemContextAArch64->X13, SystemContext.SystemContextAArch64->X14, SystemContext.SystemContextAArch64->X15));
+ DEBUG ((EFI_D_ERROR, " X16 0x%016lx X17 0x%016lx X18 0x%016lx X19 0x%016lx\n", SystemContext.SystemContextAArch64->X16, SystemContext.SystemContextAArch64->X17, SystemContext.SystemContextAArch64->X18, SystemContext.SystemContextAArch64->X19));
+ DEBUG ((EFI_D_ERROR, " X20 0x%016lx X21 0x%016lx X22 0x%016lx X23 0x%016lx\n", SystemContext.SystemContextAArch64->X20, SystemContext.SystemContextAArch64->X21, SystemContext.SystemContextAArch64->X22, SystemContext.SystemContextAArch64->X23));
+ DEBUG ((EFI_D_ERROR, " X24 0x%016lx X25 0x%016lx X26 0x%016lx X27 0x%016lx\n", SystemContext.SystemContextAArch64->X24, SystemContext.SystemContextAArch64->X25, SystemContext.SystemContextAArch64->X26, SystemContext.SystemContextAArch64->X27));
+ DEBUG ((EFI_D_ERROR, " X28 0x%016lx FP 0x%016lx LR 0x%016lx \n", SystemContext.SystemContextAArch64->X28, SystemContext.SystemContextAArch64->FP, SystemContext.SystemContextAArch64->LR));
+
+ /* We save these as 128bit numbers, but have to print them as two 64bit numbers,
+ so swap the 64bit words to correctly represent a 128bit number. */
+ DEBUG ((EFI_D_ERROR, "\n V0 0x%016lx %016lx V1 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V0[1], SystemContext.SystemContextAArch64->V0[0], SystemContext.SystemContextAArch64->V1[1], SystemContext.SystemContextAArch64->V1[0]));
+ DEBUG ((EFI_D_ERROR, " V2 0x%016lx %016lx V3 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V2[1], SystemContext.SystemContextAArch64->V2[0], SystemContext.SystemContextAArch64->V3[1], SystemContext.SystemContextAArch64->V3[0]));
+ DEBUG ((EFI_D_ERROR, " V4 0x%016lx %016lx V5 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V4[1], SystemContext.SystemContextAArch64->V4[0], SystemContext.SystemContextAArch64->V5[1], SystemContext.SystemContextAArch64->V5[0]));
+ DEBUG ((EFI_D_ERROR, " V6 0x%016lx %016lx V7 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V6[1], SystemContext.SystemContextAArch64->V6[0], SystemContext.SystemContextAArch64->V7[1], SystemContext.SystemContextAArch64->V7[0]));
+ DEBUG ((EFI_D_ERROR, " V8 0x%016lx %016lx V9 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V8[1], SystemContext.SystemContextAArch64->V8[0], SystemContext.SystemContextAArch64->V9[1], SystemContext.SystemContextAArch64->V9[0]));
+ DEBUG ((EFI_D_ERROR, " V10 0x%016lx %016lx V11 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V10[1], SystemContext.SystemContextAArch64->V10[0], SystemContext.SystemContextAArch64->V11[1], SystemContext.SystemContextAArch64->V11[0]));
+ DEBUG ((EFI_D_ERROR, " V12 0x%016lx %016lx V13 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V12[1], SystemContext.SystemContextAArch64->V12[0], SystemContext.SystemContextAArch64->V13[1], SystemContext.SystemContextAArch64->V13[0]));
+ DEBUG ((EFI_D_ERROR, " V14 0x%016lx %016lx V15 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V14[1], SystemContext.SystemContextAArch64->V14[0], SystemContext.SystemContextAArch64->V15[1], SystemContext.SystemContextAArch64->V15[0]));
+ DEBUG ((EFI_D_ERROR, " V16 0x%016lx %016lx V17 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V16[1], SystemContext.SystemContextAArch64->V16[0], SystemContext.SystemContextAArch64->V17[1], SystemContext.SystemContextAArch64->V17[0]));
+ DEBUG ((EFI_D_ERROR, " V18 0x%016lx %016lx V19 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V18[1], SystemContext.SystemContextAArch64->V18[0], SystemContext.SystemContextAArch64->V19[1], SystemContext.SystemContextAArch64->V19[0]));
+ DEBUG ((EFI_D_ERROR, " V20 0x%016lx %016lx V21 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V20[1], SystemContext.SystemContextAArch64->V20[0], SystemContext.SystemContextAArch64->V21[1], SystemContext.SystemContextAArch64->V21[0]));
+ DEBUG ((EFI_D_ERROR, " V22 0x%016lx %016lx V23 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V22[1], SystemContext.SystemContextAArch64->V22[0], SystemContext.SystemContextAArch64->V23[1], SystemContext.SystemContextAArch64->V23[0]));
+ DEBUG ((EFI_D_ERROR, " V24 0x%016lx %016lx V25 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V24[1], SystemContext.SystemContextAArch64->V24[0], SystemContext.SystemContextAArch64->V25[1], SystemContext.SystemContextAArch64->V25[0]));
+ DEBUG ((EFI_D_ERROR, " V26 0x%016lx %016lx V27 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V26[1], SystemContext.SystemContextAArch64->V26[0], SystemContext.SystemContextAArch64->V27[1], SystemContext.SystemContextAArch64->V27[0]));
+ DEBUG ((EFI_D_ERROR, " V28 0x%016lx %016lx V29 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V28[1], SystemContext.SystemContextAArch64->V28[0], SystemContext.SystemContextAArch64->V29[1], SystemContext.SystemContextAArch64->V29[0]));
+ DEBUG ((EFI_D_ERROR, " V30 0x%016lx %016lx V31 0x%016lx %016lx\n", SystemContext.SystemContextAArch64->V30[1], SystemContext.SystemContextAArch64->V30[0], SystemContext.SystemContextAArch64->V31[1], SystemContext.SystemContextAArch64->V31[0]));
+
+ DEBUG ((EFI_D_ERROR, "\n SP 0x%016lx ELR 0x%016lx SPSR 0x%08lx FPSR 0x%08lx\n ESR 0x%08lx FAR 0x%016lx\n", SystemContext.SystemContextAArch64->SP, SystemContext.SystemContextAArch64->ELR, SystemContext.SystemContextAArch64->SPSR, SystemContext.SystemContextAArch64->FPSR, SystemContext.SystemContextAArch64->ESR, SystemContext.SystemContextAArch64->FAR));
+
+ DEBUG ((EFI_D_ERROR, "\n ESR : EC 0x%02x IL 0x%x ISS 0x%08x\n", (SystemContext.SystemContextAArch64->ESR & 0xFC000000) >> 26, (SystemContext.SystemContextAArch64->ESR >> 25) & 0x1, SystemContext.SystemContextAArch64->ESR & 0x1FFFFFF ));
+
+ DescribeExceptionSyndrome (SystemContext.SystemContextAArch64->ESR);
+
+ DEBUG ((EFI_D_ERROR, "\nStack dump:\n"));
+ for (Offset = -256; Offset < 256; Offset += 32) {
+ DEBUG ((EFI_D_ERROR, "%c %013lx: %016lx %016lx %016lx %016lx\n",
+ Offset == 0 ? '>' : ' ',
+ SystemContext.SystemContextAArch64->SP + Offset,
+ *(UINT64 *)(SystemContext.SystemContextAArch64->SP + Offset),
+ *(UINT64 *)(SystemContext.SystemContextAArch64->SP + Offset + 8),
+ *(UINT64 *)(SystemContext.SystemContextAArch64->SP + Offset + 16),
+ *(UINT64 *)(SystemContext.SystemContextAArch64->SP + Offset + 24)));
+ }
+
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
diff --git a/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c new file mode 100644 index 000000000..fa9af8c41 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c @@ -0,0 +1,277 @@ +/** @file
+ Default exception handler
+
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2012, ARM Ltd. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ArmDisassemblerLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Guid/DebugImageInfoTable.h>
+
+#include <Protocol/DebugSupport.h>
+#include <Library/DefaultExceptionHandlerLib.h>
+
+//
+// The number of elements in a CHAR8 array, including the terminating NUL, that
+// is meant to hold the string rendering of the CPSR.
+//
+#define CPSR_STRING_SIZE 32
+
+typedef struct {
+ UINT32 BIT;
+ CHAR8 Char;
+} CPSR_CHAR;
+
+CHAR8 *
+GetImageName (
+ IN UINTN FaultAddress,
+ OUT UINTN *ImageBase,
+ OUT UINTN *PeCoffSizeOfHeaders
+ );
+
+/**
+ Convert the Current Program Status Register (CPSR) to a string. The string is
+ a defacto standard in the ARM world.
+
+ It is possible to add extra bits by adding them to CpsrChar array.
+
+ @param Cpsr ARM CPSR register value
+ @param ReturnStr CPSR_STRING_SIZE byte string that contains string
+ version of CPSR
+
+**/
+VOID
+CpsrString (
+ IN UINT32 Cpsr,
+ OUT CHAR8 *ReturnStr
+ )
+{
+ UINTN Index;
+ CHAR8* Str;
+ CHAR8* ModeStr;
+ CPSR_CHAR CpsrChar[] = {
+ { 31, 'n' },
+ { 30, 'z' },
+ { 29, 'c' },
+ { 28, 'v' },
+
+ { 9, 'e' },
+ { 8, 'a' },
+ { 7, 'i' },
+ { 6, 'f' },
+ { 5, 't' },
+ { 0, '?' }
+ };
+
+ Str = ReturnStr;
+
+ for (Index = 0; CpsrChar[Index].BIT != 0; Index++, Str++) {
+ *Str = CpsrChar[Index].Char;
+ if ((Cpsr & (1 << CpsrChar[Index].BIT)) != 0) {
+ // Concert to upper case if bit is set
+ *Str &= ~0x20;
+ }
+ }
+
+ *Str++ = '_';
+ *Str = '\0';
+
+ switch (Cpsr & 0x1f) {
+ case 0x10:
+ ModeStr = "usr";
+ break;
+ case 0x011:
+ ModeStr = "fiq";
+ break;
+ case 0x12:
+ ModeStr = "irq";
+ break;
+ case 0x13:
+ ModeStr = "svc";
+ break;
+ case 0x16:
+ ModeStr = "mon";
+ break;
+ case 0x17:
+ ModeStr = "abt";
+ break;
+ case 0x1b:
+ ModeStr = "und";
+ break;
+ case 0x1f:
+ ModeStr = "sys";
+ break;
+
+ default:
+ ModeStr = "???";
+ break;
+ }
+
+ //
+ // See the interface contract in the leading comment block.
+ //
+ AsciiStrCatS (Str, CPSR_STRING_SIZE - (Str - ReturnStr), ModeStr);
+}
+
+CHAR8 *
+FaultStatusToString (
+ IN UINT32 Status
+ )
+{
+ CHAR8 *FaultSource;
+
+ switch (Status) {
+ case 0x01: FaultSource = "Alignment fault"; break;
+ case 0x02: FaultSource = "Debug event fault"; break;
+ case 0x03: FaultSource = "Access Flag fault on Section"; break;
+ case 0x04: FaultSource = "Cache maintenance operation fault[2]"; break;
+ case 0x05: FaultSource = "Translation fault on Section"; break;
+ case 0x06: FaultSource = "Access Flag fault on Page"; break;
+ case 0x07: FaultSource = "Translation fault on Page"; break;
+ case 0x08: FaultSource = "Precise External Abort"; break;
+ case 0x09: FaultSource = "Domain fault on Section"; break;
+ case 0x0b: FaultSource = "Domain fault on Page"; break;
+ case 0x0c: FaultSource = "External abort on translation, first level"; break;
+ case 0x0d: FaultSource = "Permission fault on Section"; break;
+ case 0x0e: FaultSource = "External abort on translation, second level"; break;
+ case 0x0f: FaultSource = "Permission fault on Page"; break;
+ case 0x16: FaultSource = "Imprecise External Abort"; break;
+ default: FaultSource = "No function"; break;
+ }
+
+ return FaultSource;
+}
+
+STATIC CHAR8 *gExceptionTypeString[] = {
+ "Reset",
+ "Undefined OpCode",
+ "SVC",
+ "Prefetch Abort",
+ "Data Abort",
+ "Undefined",
+ "IRQ",
+ "FIQ"
+};
+
+/**
+ This is the default action to take on an unexpected exception
+
+ Since this is exception context don't do anything crazy like try to allocate memory.
+
+ @param ExceptionType Type of the exception
+ @param SystemContext Register state at the time of the Exception
+
+
+**/
+VOID
+DefaultExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ CHAR8 Buffer[100];
+ UINTN CharCount;
+ UINT32 DfsrStatus;
+ UINT32 IfsrStatus;
+ BOOLEAN DfsrWrite;
+ UINT32 PcAdjust = 0;
+
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"\n%a Exception PC at 0x%08x CPSR 0x%08x ",
+ gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC, SystemContext.SystemContextArm->CPSR);
+ SerialPortWrite ((UINT8 *)Buffer, CharCount);
+ if (gST->ConOut != NULL) {
+ AsciiPrint (Buffer);
+ }
+
+ DEBUG_CODE_BEGIN ();
+ CHAR8 *Pdb;
+ UINT32 ImageBase;
+ UINT32 PeCoffSizeOfHeader;
+ UINT32 Offset;
+ CHAR8 CpsrStr[CPSR_STRING_SIZE]; // char per bit. Lower 5-bits are mode
+ // that is a 3 char string
+ CHAR8 Buffer[80];
+ UINT8 *DisAsm;
+ UINT32 ItBlock;
+
+ CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);
+ DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr));
+
+ Pdb = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader);
+ Offset = SystemContext.SystemContextArm->PC - ImageBase;
+ if (Pdb != NULL) {
+ DEBUG ((EFI_D_ERROR, "%a\n", Pdb));
+
+ //
+ // A PE/COFF image loads its headers into memory so the headers are
+ // included in the linked addresses. ELF and Mach-O images do not
+ // include the headers so the first byte of the image is usually
+ // text (code). If you look at link maps from ELF or Mach-O images
+ // you need to subtract out the size of the PE/COFF header to get
+ // get the offset that matches the link map.
+ //
+ DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));
+
+ // If we come from an image it is safe to show the instruction. We know it should not fault
+ DisAsm = (UINT8 *)(UINTN)SystemContext.SystemContextArm->PC;
+ ItBlock = 0;
+ DisassembleInstruction (&DisAsm, (SystemContext.SystemContextArm->CPSR & BIT5) == BIT5, TRUE, &ItBlock, Buffer, sizeof (Buffer));
+ DEBUG ((EFI_D_ERROR, "\n%a", Buffer));
+
+ switch (ExceptionType) {
+ case EXCEPT_ARM_UNDEFINED_INSTRUCTION:
+ case EXCEPT_ARM_SOFTWARE_INTERRUPT:
+ case EXCEPT_ARM_PREFETCH_ABORT:
+ case EXCEPT_ARM_DATA_ABORT:
+ // advance PC past the faulting instruction
+ PcAdjust = (UINTN)DisAsm - SystemContext.SystemContextArm->PC;
+ break;
+
+ default:
+ break;
+ }
+
+ }
+ DEBUG_CODE_END ();
+ DEBUG ((EFI_D_ERROR, "\n R0 0x%08x R1 0x%08x R2 0x%08x R3 0x%08x\n", SystemContext.SystemContextArm->R0, SystemContext.SystemContextArm->R1, SystemContext.SystemContextArm->R2, SystemContext.SystemContextArm->R3));
+ DEBUG ((EFI_D_ERROR, " R4 0x%08x R5 0x%08x R6 0x%08x R7 0x%08x\n", SystemContext.SystemContextArm->R4, SystemContext.SystemContextArm->R5, SystemContext.SystemContextArm->R6, SystemContext.SystemContextArm->R7));
+ DEBUG ((EFI_D_ERROR, " R8 0x%08x R9 0x%08x R10 0x%08x R11 0x%08x\n", SystemContext.SystemContextArm->R8, SystemContext.SystemContextArm->R9, SystemContext.SystemContextArm->R10, SystemContext.SystemContextArm->R11));
+ DEBUG ((EFI_D_ERROR, " R12 0x%08x SP 0x%08x LR 0x%08x PC 0x%08x\n", SystemContext.SystemContextArm->R12, SystemContext.SystemContextArm->SP, SystemContext.SystemContextArm->LR, SystemContext.SystemContextArm->PC));
+ DEBUG ((EFI_D_ERROR, "DFSR 0x%08x DFAR 0x%08x IFSR 0x%08x IFAR 0x%08x\n", SystemContext.SystemContextArm->DFSR, SystemContext.SystemContextArm->DFAR, SystemContext.SystemContextArm->IFSR, SystemContext.SystemContextArm->IFAR));
+
+ // Bit10 is Status[4] Bit3:0 is Status[3:0]
+ DfsrStatus = (SystemContext.SystemContextArm->DFSR & 0xf) | ((SystemContext.SystemContextArm->DFSR >> 6) & 0x10);
+ DfsrWrite = (SystemContext.SystemContextArm->DFSR & BIT11) != 0;
+ if (DfsrStatus != 0x00) {
+ DEBUG ((EFI_D_ERROR, " %a: %a 0x%08x\n", FaultStatusToString (DfsrStatus), DfsrWrite ? "write to" : "read from", SystemContext.SystemContextArm->DFAR));
+ }
+
+ IfsrStatus = (SystemContext.SystemContextArm->IFSR & 0xf) | ((SystemContext.SystemContextArm->IFSR >> 6) & 0x10);
+ if (IfsrStatus != 0) {
+ DEBUG ((EFI_D_ERROR, " Instruction %a at 0x%08x\n", FaultStatusToString (SystemContext.SystemContextArm->IFSR & 0xf), SystemContext.SystemContextArm->IFAR));
+ }
+
+ DEBUG ((EFI_D_ERROR, "\n"));
+ ASSERT (FALSE);
+
+ CpuDeadLoop (); // may return if executing under a debugger
+
+ // Clear the error registers that we have already displayed incase some one wants to keep going
+ SystemContext.SystemContextArm->DFSR = 0;
+ SystemContext.SystemContextArm->IFSR = 0;
+
+ // If some one is stepping past the exception handler adjust the PC to point to the next instruction
+ SystemContext.SystemContextArm->PC += PcAdjust;
+}
diff --git a/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf new file mode 100644 index 000000000..c7d31f640 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf @@ -0,0 +1,43 @@ +#/** @file
+#
+# Copyright (c) 2008, Apple Inc. All rights reserved.<BR>
+# Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DefaultExceptionHandlerLib
+ FILE_GUID = EACDB354-DF1A-4AF9-A171-499737ED818F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DefaultExceptionHandlerLib|DXE_CORE DXE_DRIVER
+
+[Sources.common]
+ DefaultExceptionHandlerUefi.c
+
+[Sources.ARM]
+ Arm/DefaultExceptionHandler.c
+
+[Sources.AARCH64]
+ AArch64/DefaultExceptionHandler.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ BaseLib
+ PrintLib
+ DebugLib
+ PeCoffGetEntryPointLib
+ ArmDisassemblerLib
+ SerialPortLib
+ UefiBootServicesTableLib
+
+[Guids]
+ gEfiDebugImageInfoTableGuid
diff --git a/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c new file mode 100644 index 000000000..e9fea4038 --- /dev/null +++ b/roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c @@ -0,0 +1,69 @@ +/** @file
+
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/UefiLib.h>
+
+#include <Guid/DebugImageInfoTable.h>
+
+/**
+ Use the EFI Debug Image Table to lookup the FaultAddress and find which PE/COFF image
+ it came from. As long as the PE/COFF image contains a debug directory entry a
+ string can be returned. For ELF and Mach-O images the string points to the Mach-O or ELF
+ image. Microsoft tools contain a pointer to the PDB file that contains the debug information.
+
+ @param FaultAddress Address to find PE/COFF image for.
+ @param ImageBase Return load address of found image
+ @param PeCoffSizeOfHeaders Return the size of the PE/COFF header for the image that was found
+
+ @retval NULL FaultAddress not in a loaded PE/COFF image.
+ @retval Path and file name of PE/COFF image.
+
+**/
+CHAR8 *
+GetImageName (
+ IN UINTN FaultAddress,
+ OUT UINTN *ImageBase,
+ OUT UINTN *PeCoffSizeOfHeaders
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *DebugTableHeader;
+ EFI_DEBUG_IMAGE_INFO *DebugTable;
+ UINTN Entry;
+ CHAR8 *Address;
+
+ Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&DebugTableHeader);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ DebugTable = DebugTableHeader->EfiDebugImageInfoTable;
+ if (DebugTable == NULL) {
+ return NULL;
+ }
+
+ Address = (CHAR8 *)(UINTN)FaultAddress;
+ for (Entry = 0; Entry < DebugTableHeader->TableSize; Entry++, DebugTable++) {
+ if (DebugTable->NormalImage != NULL) {
+ if ((DebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) &&
+ (DebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) {
+ if ((Address >= (CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase) &&
+ (Address <= ((CHAR8 *)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase + DebugTable->NormalImage->LoadedImageProtocolInstance->ImageSize))) {
+ *ImageBase = (UINTN)DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase;
+ *PeCoffSizeOfHeaders = PeCoffGetSizeOfHeaders ((VOID *)(UINTN)*ImageBase);
+ return PeCoffLoaderGetPdbPointer (DebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase);
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
|