16f72e28d04348ad4539679949609675b114896e1andrewfish/** @file
26f72e28d04348ad4539679949609675b114896e1andrewfish  Default exception handler
36f72e28d04348ad4539679949609675b114896e1andrewfish
4d6ebcab76903254f4423b7e7d3808fb0abaadb46hhtian  Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
5619b3998880e3c28c46d3a20bbbfa879e08b3579oliviermartin  Copyright (c) 2012, ARM Ltd. All rights reserved.<BR>
63402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
7d6ebcab76903254f4423b7e7d3808fb0abaadb46hhtian  This program and the accompanying materials
86f72e28d04348ad4539679949609675b114896e1andrewfish  are licensed and made available under the terms and conditions of the BSD License
96f72e28d04348ad4539679949609675b114896e1andrewfish  which accompanies this distribution.  The full text of the license may be found at
106f72e28d04348ad4539679949609675b114896e1andrewfish  http://opensource.org/licenses/bsd-license.php
116f72e28d04348ad4539679949609675b114896e1andrewfish
126f72e28d04348ad4539679949609675b114896e1andrewfish  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
136f72e28d04348ad4539679949609675b114896e1andrewfish  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
146f72e28d04348ad4539679949609675b114896e1andrewfish
156f72e28d04348ad4539679949609675b114896e1andrewfish**/
166f72e28d04348ad4539679949609675b114896e1andrewfish
176f72e28d04348ad4539679949609675b114896e1andrewfish#include <Uefi.h>
186f72e28d04348ad4539679949609675b114896e1andrewfish#include <Library/BaseLib.h>
196f72e28d04348ad4539679949609675b114896e1andrewfish#include <Library/DebugLib.h>
206f72e28d04348ad4539679949609675b114896e1andrewfish#include <Library/PeCoffGetEntryPointLib.h>
217755dfd3a51d67cd4fa9855a6911131aa0f6add8oliviermartin#include <Library/PrintLib.h>
22097bd461c4219edb62f4595ce7ccc6ec3bb34db9andrewfish#include <Library/ArmDisassemblerLib.h>
237755dfd3a51d67cd4fa9855a6911131aa0f6add8oliviermartin#include <Library/SerialPortLib.h>
246f72e28d04348ad4539679949609675b114896e1andrewfish
256f72e28d04348ad4539679949609675b114896e1andrewfish#include <Guid/DebugImageInfoTable.h>
266f72e28d04348ad4539679949609675b114896e1andrewfish
27619b3998880e3c28c46d3a20bbbfa879e08b3579oliviermartin#include <Protocol/DebugSupport.h>
28619b3998880e3c28c46d3a20bbbfa879e08b3579oliviermartin#include <Library/DefaultExceptionHandlerLib.h>
296f72e28d04348ad4539679949609675b114896e1andrewfish
306f72e28d04348ad4539679949609675b114896e1andrewfishEFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL;
316f72e28d04348ad4539679949609675b114896e1andrewfish
326f72e28d04348ad4539679949609675b114896e1andrewfishtypedef struct {
336f72e28d04348ad4539679949609675b114896e1andrewfish  UINT32  BIT;
346f72e28d04348ad4539679949609675b114896e1andrewfish  CHAR8   Char;
356f72e28d04348ad4539679949609675b114896e1andrewfish} CPSR_CHAR;
366f72e28d04348ad4539679949609675b114896e1andrewfish
376f72e28d04348ad4539679949609675b114896e1andrewfishCHAR8 *
386f72e28d04348ad4539679949609675b114896e1andrewfishGetImageName (
39c63626b7d31cb8c6ffee5870de742f4aa859fee8oliviermartin  IN  UINTN  FaultAddress,
40c63626b7d31cb8c6ffee5870de742f4aa859fee8oliviermartin  OUT UINTN  *ImageBase,
41c63626b7d31cb8c6ffee5870de742f4aa859fee8oliviermartin  OUT UINTN  *PeCoffSizeOfHeaders
42619b3998880e3c28c46d3a20bbbfa879e08b3579oliviermartin  );
436f72e28d04348ad4539679949609675b114896e1andrewfish
446f72e28d04348ad4539679949609675b114896e1andrewfish/**
453402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  Convert the Current Program Status Register (CPSR) to a string. The string is
463402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  a defacto standard in the ARM world.
473402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
486f72e28d04348ad4539679949609675b114896e1andrewfish  It is possible to add extra bits by adding them to CpsrChar array.
496f72e28d04348ad4539679949609675b114896e1andrewfish
506f72e28d04348ad4539679949609675b114896e1andrewfish  @param  Cpsr         ARM CPSR register value
516f72e28d04348ad4539679949609675b114896e1andrewfish  @param  ReturnStr    32 byte string that contains string version of CPSR
526f72e28d04348ad4539679949609675b114896e1andrewfish
536f72e28d04348ad4539679949609675b114896e1andrewfish**/
546f72e28d04348ad4539679949609675b114896e1andrewfishVOID
556f72e28d04348ad4539679949609675b114896e1andrewfishCpsrString (
566f72e28d04348ad4539679949609675b114896e1andrewfish  IN  UINT32  Cpsr,
576f72e28d04348ad4539679949609675b114896e1andrewfish  OUT CHAR8   *ReturnStr
586f72e28d04348ad4539679949609675b114896e1andrewfish  )
596f72e28d04348ad4539679949609675b114896e1andrewfish{
6011c20f4e06d252feaa65aa5e526686baf015762doliviermartin  UINTN     Index;
6111c20f4e06d252feaa65aa5e526686baf015762doliviermartin  CHAR8*    Str;
6211c20f4e06d252feaa65aa5e526686baf015762doliviermartin  CHAR8*    ModeStr;
636f72e28d04348ad4539679949609675b114896e1andrewfish  CPSR_CHAR CpsrChar[] = {
646f72e28d04348ad4539679949609675b114896e1andrewfish    { 31, 'n' },
656f72e28d04348ad4539679949609675b114896e1andrewfish    { 30, 'z' },
666f72e28d04348ad4539679949609675b114896e1andrewfish    { 29, 'c' },
676f72e28d04348ad4539679949609675b114896e1andrewfish    { 28, 'v' },
686f72e28d04348ad4539679949609675b114896e1andrewfish
696f72e28d04348ad4539679949609675b114896e1andrewfish    { 9,  'e' },
706f72e28d04348ad4539679949609675b114896e1andrewfish    { 8,  'a' },
716f72e28d04348ad4539679949609675b114896e1andrewfish    { 7,  'i' },
726f72e28d04348ad4539679949609675b114896e1andrewfish    { 6,  'f' },
736f72e28d04348ad4539679949609675b114896e1andrewfish    { 5,  't' },
746f72e28d04348ad4539679949609675b114896e1andrewfish    { 0,  '?' }
756f72e28d04348ad4539679949609675b114896e1andrewfish  };
763402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
7711c20f4e06d252feaa65aa5e526686baf015762doliviermartin  Str = ReturnStr;
7811c20f4e06d252feaa65aa5e526686baf015762doliviermartin
796f72e28d04348ad4539679949609675b114896e1andrewfish  for (Index = 0; CpsrChar[Index].BIT != 0; Index++, Str++) {
806f72e28d04348ad4539679949609675b114896e1andrewfish    *Str = CpsrChar[Index].Char;
816f72e28d04348ad4539679949609675b114896e1andrewfish    if ((Cpsr & (1 << CpsrChar[Index].BIT)) != 0) {
826f72e28d04348ad4539679949609675b114896e1andrewfish      // Concert to upper case if bit is set
836f72e28d04348ad4539679949609675b114896e1andrewfish      *Str &= ~0x20;
846f72e28d04348ad4539679949609675b114896e1andrewfish    }
856f72e28d04348ad4539679949609675b114896e1andrewfish  }
863402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
876f72e28d04348ad4539679949609675b114896e1andrewfish  *Str++ = '_';
886f72e28d04348ad4539679949609675b114896e1andrewfish  *Str = '\0';
893402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
906f72e28d04348ad4539679949609675b114896e1andrewfish  switch (Cpsr & 0x1f) {
916f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x10:
926f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "usr";
936f72e28d04348ad4539679949609675b114896e1andrewfish    break;
946f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x011:
956f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "fiq";
966f72e28d04348ad4539679949609675b114896e1andrewfish    break;
976f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x12:
986f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "irq";
996f72e28d04348ad4539679949609675b114896e1andrewfish    break;
1006f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x13:
1016f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "svc";
1026f72e28d04348ad4539679949609675b114896e1andrewfish    break;
1036f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x16:
1046f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "mon";
1056f72e28d04348ad4539679949609675b114896e1andrewfish    break;
1066f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x17:
1076f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "abt";
1086f72e28d04348ad4539679949609675b114896e1andrewfish    break;
1096f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x1b:
1106f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "und";
1116f72e28d04348ad4539679949609675b114896e1andrewfish    break;
1126f72e28d04348ad4539679949609675b114896e1andrewfish  case 0x1f:
1136f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "sys";
1146f72e28d04348ad4539679949609675b114896e1andrewfish    break;
1153402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1166f72e28d04348ad4539679949609675b114896e1andrewfish  default:
1176f72e28d04348ad4539679949609675b114896e1andrewfish    ModeStr = "???";
1186f72e28d04348ad4539679949609675b114896e1andrewfish    break;
1196f72e28d04348ad4539679949609675b114896e1andrewfish  }
1203402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1216f72e28d04348ad4539679949609675b114896e1andrewfish  AsciiStrCat (Str, ModeStr);
1226f72e28d04348ad4539679949609675b114896e1andrewfish  return;
1233402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron}
124d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish
125d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfishCHAR8 *
126d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfishFaultStatusToString (
127d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  IN  UINT32  Status
128d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  )
129d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish{
130d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  CHAR8 *FaultSource;
131d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish
132d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  switch (Status) {
133d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x01: FaultSource = "Alignment fault"; break;
134d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x02: FaultSource = "Debug event fault"; break;
135d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x03: FaultSource = "Access Flag fault on Section"; break;
136d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x04: FaultSource = "Cache maintenance operation fault[2]"; break;
137d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x05: FaultSource = "Translation fault on Section"; break;
138d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x06: FaultSource = "Access Flag fault on Page"; break;
139d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x07: FaultSource = "Translation fault on Page"; break;
140d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x08: FaultSource = "Precise External Abort"; break;
141d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x09: FaultSource = "Domain fault on Section"; break;
142d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x0b: FaultSource = "Domain fault on Page"; break;
143d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x0c: FaultSource = "External abort on translation, first level"; break;
144d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x0d: FaultSource = "Permission fault on Section"; break;
145d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x0e: FaultSource = "External abort on translation, second level"; break;
146d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x0f: FaultSource = "Permission fault on Page"; break;
147d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    case 0x16: FaultSource = "Imprecise External Abort"; break;
148d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    default:   FaultSource = "No function"; break;
149d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    }
150d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish
151d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  return FaultSource;
152d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish}
153d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish
15411c20f4e06d252feaa65aa5e526686baf015762doliviermartinSTATIC CHAR8 *gExceptionTypeString[] = {
1556f72e28d04348ad4539679949609675b114896e1andrewfish  "Reset",
1566f72e28d04348ad4539679949609675b114896e1andrewfish  "Undefined OpCode",
157619b3998880e3c28c46d3a20bbbfa879e08b3579oliviermartin  "SVC",
1586f72e28d04348ad4539679949609675b114896e1andrewfish  "Prefetch Abort",
1596f72e28d04348ad4539679949609675b114896e1andrewfish  "Data Abort",
1606f72e28d04348ad4539679949609675b114896e1andrewfish  "Undefined",
1616f72e28d04348ad4539679949609675b114896e1andrewfish  "IRQ",
1626f72e28d04348ad4539679949609675b114896e1andrewfish  "FIQ"
1636f72e28d04348ad4539679949609675b114896e1andrewfish};
1646f72e28d04348ad4539679949609675b114896e1andrewfish
1656f72e28d04348ad4539679949609675b114896e1andrewfish/**
1666f72e28d04348ad4539679949609675b114896e1andrewfish  This is the default action to take on an unexpected exception
1673402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
1686f72e28d04348ad4539679949609675b114896e1andrewfish  Since this is exception context don't do anything crazy like try to allcoate memory.
1696f72e28d04348ad4539679949609675b114896e1andrewfish
1706f72e28d04348ad4539679949609675b114896e1andrewfish  @param  ExceptionType    Type of the exception
1716f72e28d04348ad4539679949609675b114896e1andrewfish  @param  SystemContext    Register state at the time of the Exception
1726f72e28d04348ad4539679949609675b114896e1andrewfish
1736f72e28d04348ad4539679949609675b114896e1andrewfish
1746f72e28d04348ad4539679949609675b114896e1andrewfish**/
1756f72e28d04348ad4539679949609675b114896e1andrewfishVOID
1766f72e28d04348ad4539679949609675b114896e1andrewfishDefaultExceptionHandler (
1776f72e28d04348ad4539679949609675b114896e1andrewfish  IN     EFI_EXCEPTION_TYPE           ExceptionType,
1786f72e28d04348ad4539679949609675b114896e1andrewfish  IN OUT EFI_SYSTEM_CONTEXT           SystemContext
1796f72e28d04348ad4539679949609675b114896e1andrewfish  )
1806f72e28d04348ad4539679949609675b114896e1andrewfish{
1817755dfd3a51d67cd4fa9855a6911131aa0f6add8oliviermartin  CHAR8     Buffer[100];
1827755dfd3a51d67cd4fa9855a6911131aa0f6add8oliviermartin  UINTN     CharCount;
183d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  UINT32    DfsrStatus;
18465e27445877ff101115c79e76928d91bf7625876andrewfish  UINT32    IfsrStatus;
185d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  BOOLEAN   DfsrWrite;
186d629c28396030c476b77e3f4c552da201e4dffe5andrewfish  UINT32    PcAdjust = 0;
1876f72e28d04348ad4539679949609675b114896e1andrewfish
1887755dfd3a51d67cd4fa9855a6911131aa0f6add8oliviermartin  CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"\n%a Exception PC at 0x%08x  CPSR 0x%08x ",
18991c38d4e94c1461f5824b83d3722fe46626aa0d3Ronald Cron         gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC, SystemContext.SystemContextArm->CPSR);
1907755dfd3a51d67cd4fa9855a6911131aa0f6add8oliviermartin  SerialPortWrite ((UINT8 *) Buffer, CharCount);
1917755dfd3a51d67cd4fa9855a6911131aa0f6add8oliviermartin
1926f72e28d04348ad4539679949609675b114896e1andrewfish  DEBUG_CODE_BEGIN ();
1936f72e28d04348ad4539679949609675b114896e1andrewfish    CHAR8   *Pdb;
1946f72e28d04348ad4539679949609675b114896e1andrewfish    UINT32  ImageBase;
1956f72e28d04348ad4539679949609675b114896e1andrewfish    UINT32  PeCoffSizeOfHeader;
1966f72e28d04348ad4539679949609675b114896e1andrewfish    UINT32  Offset;
1976f72e28d04348ad4539679949609675b114896e1andrewfish    CHAR8   CpsrStr[32];  // char per bit. Lower 5-bits are mode that is a 3 char string
1986f72e28d04348ad4539679949609675b114896e1andrewfish    CHAR8   Buffer[80];
199097bd461c4219edb62f4595ce7ccc6ec3bb34db9andrewfish    UINT8   *DisAsm;
200f3198cba84f56f85281b87c4e9bf96e77a934f16andrewfish    UINT32  ItBlock;
2013402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2026f72e28d04348ad4539679949609675b114896e1andrewfish    CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);
2036f72e28d04348ad4539679949609675b114896e1andrewfish    DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr));
2043402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2056f72e28d04348ad4539679949609675b114896e1andrewfish    Pdb = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader);
2066f72e28d04348ad4539679949609675b114896e1andrewfish    Offset = SystemContext.SystemContextArm->PC - ImageBase;
2076f72e28d04348ad4539679949609675b114896e1andrewfish    if (Pdb != NULL) {
2086f72e28d04348ad4539679949609675b114896e1andrewfish      DEBUG ((EFI_D_ERROR, "%a\n", Pdb));
2096f72e28d04348ad4539679949609675b114896e1andrewfish
2106f72e28d04348ad4539679949609675b114896e1andrewfish      //
2113402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron      // A PE/COFF image loads its headers into memory so the headers are
21211c20f4e06d252feaa65aa5e526686baf015762doliviermartin      // included in the linked addresses. ELF and Mach-O images do not
2136f72e28d04348ad4539679949609675b114896e1andrewfish      // include the headers so the first byte of the image is usually
2146f72e28d04348ad4539679949609675b114896e1andrewfish      // text (code). If you look at link maps from ELF or Mach-O images
21511c20f4e06d252feaa65aa5e526686baf015762doliviermartin      // you need to subtract out the size of the PE/COFF header to get
2163402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron      // get the offset that matches the link map.
2176f72e28d04348ad4539679949609675b114896e1andrewfish      //
2186f72e28d04348ad4539679949609675b114896e1andrewfish      DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));
2193402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
2206f72e28d04348ad4539679949609675b114896e1andrewfish      // If we come from an image it is safe to show the instruction. We know it should not fault
221097bd461c4219edb62f4595ce7ccc6ec3bb34db9andrewfish      DisAsm = (UINT8 *)(UINTN)SystemContext.SystemContextArm->PC;
222f3198cba84f56f85281b87c4e9bf96e77a934f16andrewfish      ItBlock = 0;
223f3198cba84f56f85281b87c4e9bf96e77a934f16andrewfish      DisassembleInstruction (&DisAsm, (SystemContext.SystemContextArm->CPSR & BIT5) == BIT5, TRUE, &ItBlock, Buffer, sizeof (Buffer));
224097bd461c4219edb62f4595ce7ccc6ec3bb34db9andrewfish      DEBUG ((EFI_D_ERROR, "\n%a", Buffer));
2253402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
226d629c28396030c476b77e3f4c552da201e4dffe5andrewfish      switch (ExceptionType) {
227d629c28396030c476b77e3f4c552da201e4dffe5andrewfish      case EXCEPT_ARM_UNDEFINED_INSTRUCTION:
228d629c28396030c476b77e3f4c552da201e4dffe5andrewfish      case EXCEPT_ARM_SOFTWARE_INTERRUPT:
229d629c28396030c476b77e3f4c552da201e4dffe5andrewfish      case EXCEPT_ARM_PREFETCH_ABORT:
230d629c28396030c476b77e3f4c552da201e4dffe5andrewfish      case EXCEPT_ARM_DATA_ABORT:
231d629c28396030c476b77e3f4c552da201e4dffe5andrewfish        // advance PC past the faulting instruction
232d629c28396030c476b77e3f4c552da201e4dffe5andrewfish        PcAdjust = (UINTN)DisAsm - SystemContext.SystemContextArm->PC;
233d629c28396030c476b77e3f4c552da201e4dffe5andrewfish        break;
2343402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
235d629c28396030c476b77e3f4c552da201e4dffe5andrewfish      default:
236d629c28396030c476b77e3f4c552da201e4dffe5andrewfish        break;
237d629c28396030c476b77e3f4c552da201e4dffe5andrewfish      }
238097bd461c4219edb62f4595ce7ccc6ec3bb34db9andrewfish
2396f72e28d04348ad4539679949609675b114896e1andrewfish    }
2406f72e28d04348ad4539679949609675b114896e1andrewfish  DEBUG_CODE_END ();
2416f72e28d04348ad4539679949609675b114896e1andrewfish  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));
2426f72e28d04348ad4539679949609675b114896e1andrewfish  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));
2436f72e28d04348ad4539679949609675b114896e1andrewfish  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));
2446f72e28d04348ad4539679949609675b114896e1andrewfish  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));
245d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  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));
246d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish
247d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  // Bit10 is Status[4] Bit3:0 is Status[3:0]
248d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  DfsrStatus = (SystemContext.SystemContextArm->DFSR & 0xf) | ((SystemContext.SystemContextArm->DFSR >> 6) & 0x10);
249d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  DfsrWrite = (SystemContext.SystemContextArm->DFSR & BIT11) != 0;
250d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  if (DfsrStatus != 0x00) {
251d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish    DEBUG ((EFI_D_ERROR, " %a: %a 0x%08x\n", FaultStatusToString (DfsrStatus), DfsrWrite ? "write to" : "read from", SystemContext.SystemContextArm->DFAR));
252d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  }
25365e27445877ff101115c79e76928d91bf7625876andrewfish
25465e27445877ff101115c79e76928d91bf7625876andrewfish  IfsrStatus = (SystemContext.SystemContextArm->IFSR & 0xf) | ((SystemContext.SystemContextArm->IFSR >> 6) & 0x10);
25565e27445877ff101115c79e76928d91bf7625876andrewfish  if (IfsrStatus != 0) {
25665e27445877ff101115c79e76928d91bf7625876andrewfish    DEBUG ((EFI_D_ERROR, " Instruction %a at 0x%08x\n", FaultStatusToString (SystemContext.SystemContextArm->IFSR & 0xf), SystemContext.SystemContextArm->IFAR));
257d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  }
2586f72e28d04348ad4539679949609675b114896e1andrewfish
259d5b0f232f77a0e1e86dc9d63c879eb486f15b1c4andrewfish  DEBUG ((EFI_D_ERROR, "\n"));
2606f72e28d04348ad4539679949609675b114896e1andrewfish  ASSERT (FALSE);
2613402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron
262bb02cb8071e9df25cbcae15a9afa70d6387320cbandrewfish  // Clear the error registers that we have already displayed incase some one wants to keep going
263bb02cb8071e9df25cbcae15a9afa70d6387320cbandrewfish  SystemContext.SystemContextArm->DFSR = 0;
264bb02cb8071e9df25cbcae15a9afa70d6387320cbandrewfish  SystemContext.SystemContextArm->IFSR = 0;
265bb02cb8071e9df25cbcae15a9afa70d6387320cbandrewfish
2663402aac7d985bf8a9f9d3c639f3fe93609380513Ronald Cron  // If some one is stepping past the exception handler adjust the PC to point to the next instruction
267d629c28396030c476b77e3f4c552da201e4dffe5andrewfish  SystemContext.SystemContextArm->PC += PcAdjust;
2686f72e28d04348ad4539679949609675b114896e1andrewfish}
269