]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c
IntelFsp2Pkg: Add FspmArchConfigPpi to support Dispatch mode
[mirror_edk2.git] / ArmPkg / Library / DefaultExceptionHandlerLib / Arm / DefaultExceptionHandler.c
CommitLineData
6f72e28d 1/** @file\r
2 Default exception handler\r
3\r
d6ebcab7 4 Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
619b3998 5 Copyright (c) 2012, ARM Ltd. All rights reserved.<BR>\r
3402aac7 6\r
d6ebcab7 7 This program and the accompanying materials\r
6f72e28d 8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include <Uefi.h>\r
6f72e28d 18#include <Library/BaseLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/PeCoffGetEntryPointLib.h>\r
7755dfd3 21#include <Library/PrintLib.h>\r
097bd461 22#include <Library/ArmDisassemblerLib.h>\r
7755dfd3 23#include <Library/SerialPortLib.h>\r
31f53880 24#include <Library/UefiBootServicesTableLib.h>\r
6f72e28d 25\r
26#include <Guid/DebugImageInfoTable.h>\r
6f72e28d 27\r
619b3998 28#include <Protocol/DebugSupport.h>\r
29#include <Library/DefaultExceptionHandlerLib.h>\r
6f72e28d 30\r
a1848bc0
LE
31//\r
32// The number of elements in a CHAR8 array, including the terminating NUL, that\r
33// is meant to hold the string rendering of the CPSR.\r
34//\r
35#define CPSR_STRING_SIZE 32\r
36\r
6f72e28d 37typedef struct {\r
38 UINT32 BIT;\r
39 CHAR8 Char;\r
40} CPSR_CHAR;\r
41\r
6f72e28d 42CHAR8 *\r
43GetImageName (\r
c63626b7 44 IN UINTN FaultAddress,\r
45 OUT UINTN *ImageBase,\r
46 OUT UINTN *PeCoffSizeOfHeaders\r
619b3998 47 );\r
6f72e28d 48\r
49/**\r
3402aac7
RC
50 Convert the Current Program Status Register (CPSR) to a string. The string is\r
51 a defacto standard in the ARM world.\r
52\r
6f72e28d 53 It is possible to add extra bits by adding them to CpsrChar array.\r
54\r
55 @param Cpsr ARM CPSR register value\r
a1848bc0
LE
56 @param ReturnStr CPSR_STRING_SIZE byte string that contains string\r
57 version of CPSR\r
6f72e28d 58\r
59**/\r
60VOID\r
61CpsrString (\r
62 IN UINT32 Cpsr,\r
63 OUT CHAR8 *ReturnStr\r
64 )\r
65{\r
11c20f4e 66 UINTN Index;\r
67 CHAR8* Str;\r
68 CHAR8* ModeStr;\r
6f72e28d 69 CPSR_CHAR CpsrChar[] = {\r
70 { 31, 'n' },\r
71 { 30, 'z' },\r
72 { 29, 'c' },\r
73 { 28, 'v' },\r
74\r
75 { 9, 'e' },\r
76 { 8, 'a' },\r
77 { 7, 'i' },\r
78 { 6, 'f' },\r
79 { 5, 't' },\r
80 { 0, '?' }\r
81 };\r
3402aac7 82\r
11c20f4e 83 Str = ReturnStr;\r
84\r
6f72e28d 85 for (Index = 0; CpsrChar[Index].BIT != 0; Index++, Str++) {\r
86 *Str = CpsrChar[Index].Char;\r
87 if ((Cpsr & (1 << CpsrChar[Index].BIT)) != 0) {\r
88 // Concert to upper case if bit is set\r
89 *Str &= ~0x20;\r
90 }\r
91 }\r
3402aac7 92\r
6f72e28d 93 *Str++ = '_';\r
94 *Str = '\0';\r
3402aac7 95\r
6f72e28d 96 switch (Cpsr & 0x1f) {\r
97 case 0x10:\r
98 ModeStr = "usr";\r
99 break;\r
100 case 0x011:\r
101 ModeStr = "fiq";\r
102 break;\r
103 case 0x12:\r
104 ModeStr = "irq";\r
105 break;\r
106 case 0x13:\r
107 ModeStr = "svc";\r
108 break;\r
109 case 0x16:\r
110 ModeStr = "mon";\r
111 break;\r
112 case 0x17:\r
113 ModeStr = "abt";\r
114 break;\r
115 case 0x1b:\r
116 ModeStr = "und";\r
117 break;\r
118 case 0x1f:\r
119 ModeStr = "sys";\r
120 break;\r
3402aac7 121\r
6f72e28d 122 default:\r
123 ModeStr = "???";\r
124 break;\r
125 }\r
3402aac7 126\r
a1848bc0
LE
127 //\r
128 // See the interface contract in the leading comment block.\r
129 //\r
130 AsciiStrCatS (Str, CPSR_STRING_SIZE - (Str - ReturnStr), ModeStr);\r
3402aac7 131}\r
d5b0f232 132\r
133CHAR8 *\r
134FaultStatusToString (\r
135 IN UINT32 Status\r
136 )\r
137{\r
138 CHAR8 *FaultSource;\r
139\r
140 switch (Status) {\r
141 case 0x01: FaultSource = "Alignment fault"; break;\r
142 case 0x02: FaultSource = "Debug event fault"; break;\r
143 case 0x03: FaultSource = "Access Flag fault on Section"; break;\r
144 case 0x04: FaultSource = "Cache maintenance operation fault[2]"; break;\r
145 case 0x05: FaultSource = "Translation fault on Section"; break;\r
146 case 0x06: FaultSource = "Access Flag fault on Page"; break;\r
147 case 0x07: FaultSource = "Translation fault on Page"; break;\r
148 case 0x08: FaultSource = "Precise External Abort"; break;\r
149 case 0x09: FaultSource = "Domain fault on Section"; break;\r
150 case 0x0b: FaultSource = "Domain fault on Page"; break;\r
151 case 0x0c: FaultSource = "External abort on translation, first level"; break;\r
152 case 0x0d: FaultSource = "Permission fault on Section"; break;\r
153 case 0x0e: FaultSource = "External abort on translation, second level"; break;\r
154 case 0x0f: FaultSource = "Permission fault on Page"; break;\r
155 case 0x16: FaultSource = "Imprecise External Abort"; break;\r
156 default: FaultSource = "No function"; break;\r
157 }\r
158\r
159 return FaultSource;\r
160}\r
161\r
11c20f4e 162STATIC CHAR8 *gExceptionTypeString[] = {\r
6f72e28d 163 "Reset",\r
164 "Undefined OpCode",\r
619b3998 165 "SVC",\r
6f72e28d 166 "Prefetch Abort",\r
167 "Data Abort",\r
168 "Undefined",\r
169 "IRQ",\r
170 "FIQ"\r
171};\r
172\r
6f72e28d 173/**\r
174 This is the default action to take on an unexpected exception\r
3402aac7 175\r
6f72e28d 176 Since this is exception context don't do anything crazy like try to allcoate memory.\r
177\r
178 @param ExceptionType Type of the exception\r
179 @param SystemContext Register state at the time of the Exception\r
180\r
181\r
182**/\r
183VOID\r
184DefaultExceptionHandler (\r
185 IN EFI_EXCEPTION_TYPE ExceptionType,\r
186 IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
187 )\r
188{\r
7755dfd3 189 CHAR8 Buffer[100];\r
190 UINTN CharCount;\r
d5b0f232 191 UINT32 DfsrStatus;\r
65e27445 192 UINT32 IfsrStatus;\r
d5b0f232 193 BOOLEAN DfsrWrite;\r
d629c283 194 UINT32 PcAdjust = 0;\r
6f72e28d 195\r
7755dfd3 196 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"\n%a Exception PC at 0x%08x CPSR 0x%08x ",\r
91c38d4e 197 gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC, SystemContext.SystemContextArm->CPSR);\r
31f53880
AB
198 SerialPortWrite ((UINT8 *)Buffer, CharCount);\r
199 if (gST->ConOut != NULL) {\r
200 AsciiPrint (Buffer);\r
201 }\r
7755dfd3 202\r
6f72e28d 203 DEBUG_CODE_BEGIN ();\r
204 CHAR8 *Pdb;\r
205 UINT32 ImageBase;\r
206 UINT32 PeCoffSizeOfHeader;\r
207 UINT32 Offset;\r
a1848bc0
LE
208 CHAR8 CpsrStr[CPSR_STRING_SIZE]; // char per bit. Lower 5-bits are mode\r
209 // that is a 3 char string\r
6f72e28d 210 CHAR8 Buffer[80];\r
097bd461 211 UINT8 *DisAsm;\r
f3198cba 212 UINT32 ItBlock;\r
3402aac7 213\r
6f72e28d 214 CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);\r
215 DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr));\r
3402aac7 216\r
6f72e28d 217 Pdb = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader);\r
218 Offset = SystemContext.SystemContextArm->PC - ImageBase;\r
219 if (Pdb != NULL) {\r
220 DEBUG ((EFI_D_ERROR, "%a\n", Pdb));\r
221\r
222 //\r
3402aac7 223 // A PE/COFF image loads its headers into memory so the headers are\r
11c20f4e 224 // included in the linked addresses. ELF and Mach-O images do not\r
6f72e28d 225 // include the headers so the first byte of the image is usually\r
226 // text (code). If you look at link maps from ELF or Mach-O images\r
11c20f4e 227 // you need to subtract out the size of the PE/COFF header to get\r
3402aac7 228 // get the offset that matches the link map.\r
6f72e28d 229 //\r
230 DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));\r
3402aac7 231\r
6f72e28d 232 // If we come from an image it is safe to show the instruction. We know it should not fault\r
097bd461 233 DisAsm = (UINT8 *)(UINTN)SystemContext.SystemContextArm->PC;\r
f3198cba 234 ItBlock = 0;\r
235 DisassembleInstruction (&DisAsm, (SystemContext.SystemContextArm->CPSR & BIT5) == BIT5, TRUE, &ItBlock, Buffer, sizeof (Buffer));\r
097bd461 236 DEBUG ((EFI_D_ERROR, "\n%a", Buffer));\r
3402aac7 237\r
d629c283 238 switch (ExceptionType) {\r
239 case EXCEPT_ARM_UNDEFINED_INSTRUCTION:\r
240 case EXCEPT_ARM_SOFTWARE_INTERRUPT:\r
241 case EXCEPT_ARM_PREFETCH_ABORT:\r
242 case EXCEPT_ARM_DATA_ABORT:\r
243 // advance PC past the faulting instruction\r
244 PcAdjust = (UINTN)DisAsm - SystemContext.SystemContextArm->PC;\r
245 break;\r
3402aac7 246\r
d629c283 247 default:\r
248 break;\r
249 }\r
097bd461 250\r
6f72e28d 251 }\r
252 DEBUG_CODE_END ();\r
253 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));\r
254 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));\r
255 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));\r
256 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));\r
d5b0f232 257 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));\r
258\r
259 // Bit10 is Status[4] Bit3:0 is Status[3:0]\r
260 DfsrStatus = (SystemContext.SystemContextArm->DFSR & 0xf) | ((SystemContext.SystemContextArm->DFSR >> 6) & 0x10);\r
261 DfsrWrite = (SystemContext.SystemContextArm->DFSR & BIT11) != 0;\r
262 if (DfsrStatus != 0x00) {\r
263 DEBUG ((EFI_D_ERROR, " %a: %a 0x%08x\n", FaultStatusToString (DfsrStatus), DfsrWrite ? "write to" : "read from", SystemContext.SystemContextArm->DFAR));\r
264 }\r
65e27445 265\r
266 IfsrStatus = (SystemContext.SystemContextArm->IFSR & 0xf) | ((SystemContext.SystemContextArm->IFSR >> 6) & 0x10);\r
267 if (IfsrStatus != 0) {\r
268 DEBUG ((EFI_D_ERROR, " Instruction %a at 0x%08x\n", FaultStatusToString (SystemContext.SystemContextArm->IFSR & 0xf), SystemContext.SystemContextArm->IFAR));\r
d5b0f232 269 }\r
6f72e28d 270\r
d5b0f232 271 DEBUG ((EFI_D_ERROR, "\n"));\r
6f72e28d 272 ASSERT (FALSE);\r
3402aac7 273\r
5c8bc8be
AB
274 CpuDeadLoop (); // may return if executing under a debugger\r
275\r
bb02cb80 276 // Clear the error registers that we have already displayed incase some one wants to keep going\r
277 SystemContext.SystemContextArm->DFSR = 0;\r
278 SystemContext.SystemContextArm->IFSR = 0;\r
279\r
3402aac7 280 // If some one is stepping past the exception handler adjust the PC to point to the next instruction\r
d629c283 281 SystemContext.SystemContextArm->PC += PcAdjust;\r
6f72e28d 282}\r