From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../AArch64/DefaultExceptionHandler.c | 275 ++++++++++++++++++++ .../Arm/DefaultExceptionHandler.c | 277 +++++++++++++++++++++ .../DefaultExceptionHandlerLib.inf | 43 ++++ .../DefaultExceptionHandlerUefi.c | 69 +++++ 4 files changed, 664 insertions(+) create mode 100644 roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c create mode 100644 roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c create mode 100644 roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf create mode 100644 roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerUefi.c (limited to 'roms/edk2/ArmPkg/Library/DefaultExceptionHandlerLib') 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.
+ Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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.
+ Copyright (c) 2012, ARM Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +// +// 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.
+# Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+# +# 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.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include + +/** + 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; +} + -- cgit