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