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