1 /** @file
2 CPU Exception Handler Library common functions.
3
4 Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "CpuExceptionCommon.h"
16
17 //
18 // Error code flag indicating whether or not an error code will be
19 // pushed on the stack if an exception occurs.
20 //
21 // 1 means an error code will be pushed, otherwise 0
22 //
23 CONST UINT32 mErrorCodeFlag = 0x00027d00;
24
25 //
26 // Define the maximum message length
27 //
28 #define MAX_DEBUG_MESSAGE_LENGTH 0x100
29
30 CONST CHAR8 mExceptionReservedStr[] = "Reserved";
31 CONST CHAR8 *mExceptionNameStr[] = {
32 "#DE - Divide Error",
33 "#DB - Debug",
34 "NMI Interrupt",
35 "#BP - Breakpoint",
36 "#OF - Overflow",
37 "#BR - BOUND Range Exceeded",
38 "#UD - Invalid Opcode",
39 "#NM - Device Not Available",
40 "#DF - Double Fault",
41 "Coprocessor Segment Overrun",
42 "#TS - Invalid TSS",
43 "#NP - Segment Not Present",
44 "#SS - Stack Fault Fault",
45 "#GP - General Protection",
46 "#PF - Page-Fault",
47 "Reserved",
48 "#MF - x87 FPU Floating-Point Error",
49 "#AC - Alignment Check",
50 "#MC - Machine-Check",
51 "#XM - SIMD floating-point",
52 "#VE - Virtualization"
53 };
54
55 #define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *))
56
57 /**
58 Get ASCII format string exception name by exception type.
59
60 @param ExceptionType Exception type.
61
62 @return ASCII format string exception name.
63 **/
64 CONST CHAR8 *
GetExceptionNameStr(IN EFI_EXCEPTION_TYPE ExceptionType)65 GetExceptionNameStr (
66 IN EFI_EXCEPTION_TYPE ExceptionType
67 )
68 {
69 if ((UINTN) ExceptionType < EXCEPTION_KNOWN_NAME_NUM) {
70 return mExceptionNameStr[ExceptionType];
71 } else {
72 return mExceptionReservedStr;
73 }
74 }
75
76 /**
77 Prints a message to the serial port.
78
79 @param Format Format string for the message to print.
80 @param ... Variable argument list whose contents are accessed
81 based on the format string specified by Format.
82
83 **/
84 VOID
85 EFIAPI
InternalPrintMessage(IN CONST CHAR8 * Format,...)86 InternalPrintMessage (
87 IN CONST CHAR8 *Format,
88 ...
89 )
90 {
91 CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
92 VA_LIST Marker;
93
94 //
95 // Convert the message to an ASCII String
96 //
97 VA_START (Marker, Format);
98 AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
99 VA_END (Marker);
100
101 //
102 // Send the print string to a Serial Port
103 //
104 SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
105 }
106
107 /**
108 Find and display image base address and return image base and its entry point.
109
110 @param CurrentEip Current instruction pointer.
111 @param EntryPoint Return module entry point if module header is found.
112
113 @return !0 Image base address.
114 @return 0 Image header cannot be found.
115 **/
116 UINTN
FindModuleImageBase(IN UINTN CurrentEip,OUT UINTN * EntryPoint)117 FindModuleImageBase (
118 IN UINTN CurrentEip,
119 OUT UINTN *EntryPoint
120 )
121 {
122 UINTN Pe32Data;
123 EFI_IMAGE_DOS_HEADER *DosHdr;
124 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
125 VOID *PdbPointer;
126
127 //
128 // Find Image Base
129 //
130 Pe32Data = CurrentEip & ~(mImageAlignSize - 1);
131 while (Pe32Data != 0) {
132 DosHdr = (EFI_IMAGE_DOS_HEADER *) Pe32Data;
133 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
134 //
135 // DOS image header is present, so read the PE header after the DOS image header.
136 //
137 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
138 //
139 // Make sure PE header address does not overflow and is less than the initial address.
140 //
141 if (((UINTN)Hdr.Pe32 > Pe32Data) && ((UINTN)Hdr.Pe32 < CurrentEip)) {
142 if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
143 //
144 // It's PE image.
145 //
146 InternalPrintMessage ("!!!! Find PE image ");
147 *EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff);
148 break;
149 }
150 }
151 } else {
152 //
153 // DOS image header is not present, TE header is at the image base.
154 //
155 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
156 if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&
157 ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386) || Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)) {
158 //
159 // It's TE image, it TE header and Machine type match
160 //
161 InternalPrintMessage ("!!!! Find TE image ");
162 *EntryPoint = (UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
163 break;
164 }
165 }
166
167 //
168 // Not found the image base, check the previous aligned address
169 //
170 Pe32Data -= mImageAlignSize;
171 }
172
173 if (Pe32Data != 0) {
174 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data);
175 if (PdbPointer != NULL) {
176 InternalPrintMessage ("%a", PdbPointer);
177 } else {
178 InternalPrintMessage ("(No PDB) " );
179 }
180 } else {
181 InternalPrintMessage ("!!!! Can't find image information. !!!!\n");
182 }
183
184 return Pe32Data;
185 }
186
187 /**
188 Read and save reserved vector information
189
190 @param[in] VectorInfo Pointer to reserved vector list.
191 @param[out] ReservedVector Pointer to reserved vector data buffer.
192 @param[in] VectorCount Vector number to be updated.
193
194 @return EFI_SUCCESS Read and save vector info successfully.
195 @retval EFI_INVALID_PARAMETER VectorInfo includes the invalid content if VectorInfo is not NULL.
196
197 **/
198 EFI_STATUS
ReadAndVerifyVectorInfo(IN EFI_VECTOR_HANDOFF_INFO * VectorInfo,OUT RESERVED_VECTORS_DATA * ReservedVector,IN UINTN VectorCount)199 ReadAndVerifyVectorInfo (
200 IN EFI_VECTOR_HANDOFF_INFO *VectorInfo,
201 OUT RESERVED_VECTORS_DATA *ReservedVector,
202 IN UINTN VectorCount
203 )
204 {
205 while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {
206 if (VectorInfo->Attribute > EFI_VECTOR_HANDOFF_HOOK_AFTER) {
207 //
208 // If vector attrubute is invalid
209 //
210 return EFI_INVALID_PARAMETER;
211 }
212 if (VectorInfo->VectorNumber < VectorCount) {
213 ReservedVector[VectorInfo->VectorNumber].Attribute = VectorInfo->Attribute;
214 }
215 VectorInfo ++;
216 }
217 return EFI_SUCCESS;
218 }