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