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