1 /*++
2
3 Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 ReportStatusCode.c
15
16 Abstract:
17
18 Worker functions for ReportStatusCode
19
20 --*/
21
22 #include "TianoCommon.h"
23 #include "EfiCommonLib.h"
24 #include EFI_GUID_DEFINITION (StatusCodeCallerId)
25 #include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
26
27
28 VOID *
EfiConstructStatusCodeData(IN UINT16 DataSize,IN EFI_GUID * TypeGuid,IN OUT EFI_STATUS_CODE_DATA * Data)29 EfiConstructStatusCodeData (
30 IN UINT16 DataSize,
31 IN EFI_GUID *TypeGuid,
32 IN OUT EFI_STATUS_CODE_DATA *Data
33 )
34 /*++
35
36 Routine Description:
37
38 Construct stanader header for optional data passed into ReportStatusCode
39
40 Arguments:
41
42 DataSize - Size of optional data. Does not include EFI_STATUS_CODE_DATA header
43 TypeGuid - GUID to place in EFI_STATUS_CODE_DATA
44 Data - Buffer to use.
45
46 Returns:
47
48 Return pointer to Data buffer pointing past the end of EFI_STATUS_CODE_DATA
49
50 --*/
51 {
52 Data->HeaderSize = (UINT16) sizeof (EFI_STATUS_CODE_DATA);
53 Data->Size = (UINT16)(DataSize - sizeof (EFI_STATUS_CODE_DATA));
54 EfiCommonLibCopyMem (&Data->Type, TypeGuid, sizeof (EFI_GUID));
55
56 return (VOID *)(Data + 1);
57 }
58
59 EFI_STATUS
EfiDebugVPrintWorker(IN UINTN ErrorLevel,IN CHAR8 * Format,IN VA_LIST Marker,IN UINTN BufferSize,IN OUT VOID * Buffer)60 EfiDebugVPrintWorker (
61 IN UINTN ErrorLevel,
62 IN CHAR8 *Format,
63 IN VA_LIST Marker,
64 IN UINTN BufferSize,
65 IN OUT VOID *Buffer
66 )
67 /*++
68
69 Routine Description:
70
71 Worker function for DEBUG(). If Error Logging hub is loaded log ASSERT
72 information. If Error Logging hub is not loaded do nothing.
73
74 The Format string might be truncated to fit into the status code struture
75 which has the max size of EFI_STATUS_CODE_DATA_MAX_SIZE.
76
77 We use UINT64 buffers due to IPF alignment concerns.
78
79 Arguments:
80
81 ErrorLevel - If error level is set do the debug print.
82
83 Format - String to use for the print, followed by Print arguments.
84
85 Marker - VarArgs
86
87 BufferSize - Size of Buffer.
88
89 Buffer - Caller allocated buffer, contains ReportStatusCode extended data
90
91 Returns:
92
93 Status code
94
95 EFI_SUCCESS - Successfully printed
96
97 --*/
98 {
99 UINTN Index;
100 UINTN FormatStrLen;
101 UINTN RemainingStrLen;
102 UINT64 *Ptr;
103 EFI_DEBUG_INFO *EfiDebug;
104
105
106 //
107 // Build the type specific EFI_STATUS_CODE_DATA in order
108 //
109
110 //
111 // Fill in EFI_STATUS_CODE_DATA to Buffer.
112 //
113 EfiDebug = (EFI_DEBUG_INFO *)EfiConstructStatusCodeData (
114 (UINT16)BufferSize,
115 &gEfiStatusCodeDataTypeDebugGuid,
116 Buffer
117 );
118
119 //
120 // Then EFI_DEBUG_INFO
121 //
122 EfiDebug->ErrorLevel = (UINT32)ErrorLevel;
123
124 //
125 // 12 * sizeof (UINT64) byte mini Var Arg stack.
126 // That is followed by the format string.
127 //
128 for (Index = 0, Ptr = (UINT64 *)(EfiDebug + 1); Index < 12; Index++, Ptr++) {
129 *Ptr = VA_ARG (Marker, UINT64);
130 }
131
132 //
133 // Place Ascii Format string at the end
134 // Truncate it to fit into the status code structure
135 //
136 FormatStrLen = EfiAsciiStrLen (Format);
137 RemainingStrLen = EFI_STATUS_CODE_DATA_MAX_SIZE
138 - sizeof (EFI_STATUS_CODE_DATA)
139 - sizeof (EFI_DEBUG_INFO)
140 - 12 * sizeof (UINT64) - 1;
141 if (FormatStrLen > RemainingStrLen) {
142 FormatStrLen = RemainingStrLen;
143 }
144 EfiCommonLibCopyMem (Ptr, Format, FormatStrLen);
145 *((CHAR8 *) Ptr + FormatStrLen) = '\0';
146
147 return EFI_SUCCESS;
148 }
149
150
151
152 EFI_STATUS
EfiDebugAssertWorker(IN CHAR8 * Filename,IN INTN LineNumber,IN CHAR8 * Description,IN UINTN BufferSize,IN OUT VOID * Buffer)153 EfiDebugAssertWorker (
154 IN CHAR8 *Filename,
155 IN INTN LineNumber,
156 IN CHAR8 *Description,
157 IN UINTN BufferSize,
158 IN OUT VOID *Buffer
159 )
160 /*++
161
162 Routine Description:
163
164 Worker function for ASSERT (). If Error Logging hub is loaded log ASSERT
165 information. If Error Logging hub is not loaded DEADLOOP ().
166
167 We use UINT64 buffers due to IPF alignment concerns.
168
169 Arguments:
170
171 Filename - File name of failing routine.
172
173 LineNumber - Line number of failing ASSERT().
174
175 Description - Description, usually the assertion,
176
177 BufferSize - Size of Buffer.
178
179 Buffer - Caller allocated buffer, contains ReportStatusCode extendecd data
180
181 Returns:
182
183 Status code
184
185 EFI_BUFFER_TOO_SMALL - Buffer not large enough
186
187 EFI_SUCCESS - Function successfully done.
188
189 --*/
190 {
191 EFI_DEBUG_ASSERT_DATA *AssertData;
192 UINTN TotalSize;
193 CHAR8 *EndOfStr;
194
195 //
196 // Make sure it will all fit in the passed in buffer
197 //
198 TotalSize = sizeof (EFI_STATUS_CODE_DATA) + sizeof (EFI_DEBUG_ASSERT_DATA);
199 TotalSize += EfiAsciiStrLen (Filename);
200 TotalSize += EfiAsciiStrLen (Description);
201 if (TotalSize > BufferSize) {
202 return EFI_BUFFER_TOO_SMALL;
203 }
204
205 //
206 // Fill in EFI_STATUS_CODE_DATA
207 //
208 AssertData = (EFI_DEBUG_ASSERT_DATA *)
209 EfiConstructStatusCodeData (
210 (UINT16)(TotalSize - sizeof (EFI_STATUS_CODE_DATA)),
211 &gEfiStatusCodeDataTypeAssertGuid,
212 Buffer
213 );
214
215 //
216 // Fill in EFI_DEBUG_ASSERT_DATA
217 //
218 AssertData->LineNumber = (UINT32)LineNumber;
219
220 //
221 // Copy Ascii FileName including NULL.
222 //
223 EndOfStr = EfiAsciiStrCpy ((CHAR8 *)(AssertData + 1), Filename);
224
225 //
226 // Copy Ascii Description
227 //
228 EfiAsciiStrCpy (EndOfStr, Description);
229 return EFI_SUCCESS;
230 }
231
232
233
234 BOOLEAN
ReportStatusCodeExtractAssertInfo(IN EFI_STATUS_CODE_TYPE CodeType,IN EFI_STATUS_CODE_VALUE Value,IN EFI_STATUS_CODE_DATA * Data,OUT CHAR8 ** Filename,OUT CHAR8 ** Description,OUT UINT32 * LineNumber)235 ReportStatusCodeExtractAssertInfo (
236 IN EFI_STATUS_CODE_TYPE CodeType,
237 IN EFI_STATUS_CODE_VALUE Value,
238 IN EFI_STATUS_CODE_DATA *Data,
239 OUT CHAR8 **Filename,
240 OUT CHAR8 **Description,
241 OUT UINT32 *LineNumber
242 )
243 /*++
244
245 Routine Description:
246
247 Extract assert information from status code data.
248
249 Arguments:
250
251 CodeType - Code type
252 Value - Code value
253 Data - Optional data associated with this status code.
254 Filename - Filename extracted from Data
255 Description - Description extracted from Data
256 LineNumber - Line number extracted from Data
257
258 Returns:
259
260 TRUE - Successfully extracted
261
262 FALSE - Extraction failed
263
264 --*/
265 {
266 EFI_DEBUG_ASSERT_DATA *AssertData;
267
268 if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
269 ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED)) {
270 //
271 // Assume if we have an uncontained unrecoverable error that the data hub
272 // may not work. So we will print out data here. If we had an IPMI controller,
273 // or error log we could wack the hardware here.
274 //
275 if ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE && (Data != NULL)) {
276 //
277 // ASSERT (Expresion) -
278 // ExtendedData == FileName
279 // Instance == Line Nuber
280 // NULL == String of Expresion
281 //
282 AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
283 *Filename = (CHAR8 *)(AssertData + 1);
284 *Description = *Filename + EfiAsciiStrLen (*Filename) + 1;
285 *LineNumber = AssertData->LineNumber;
286 return TRUE;
287 }
288 }
289 return FALSE;
290 }
291
292
293 BOOLEAN
ReportStatusCodeExtractDebugInfo(IN EFI_STATUS_CODE_DATA * Data,OUT UINT32 * ErrorLevel,OUT VA_LIST * Marker,OUT CHAR8 ** Format)294 ReportStatusCodeExtractDebugInfo (
295 IN EFI_STATUS_CODE_DATA *Data,
296 OUT UINT32 *ErrorLevel,
297 OUT VA_LIST *Marker,
298 OUT CHAR8 **Format
299 )
300 /*++
301
302 Routine Description:
303
304 Extract debug information from status code data.
305
306 Arguments:
307
308 Data - Optional data associated with status code.
309 ErrorLevel - Error level extracted from Data
310 Marker - VA_LIST extracted from Data
311 Format - Format string extracted from Data
312
313 Returns:
314
315 TRUE - Successfully extracted
316
317 FALSE - Extraction failed
318
319 --*/
320 {
321 EFI_DEBUG_INFO *DebugInfo;
322
323 if ((Data == NULL) || (!EfiCompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid))) {
324 return FALSE;
325 }
326
327 DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
328
329 *ErrorLevel = DebugInfo->ErrorLevel;
330
331 //
332 // The first 12 * UINTN bytes of the string are really an
333 // arguement stack to support varargs on the Format string.
334 //
335 #if (defined (EFIARM) || defined (EFIAARCH64) || defined (__APPLE__) || defined (__GNUC__))
336 // It is not legal C code to cast VA_LIST to a pointer. VA_LIST can
337 // be a structure.
338 return FALSE;
339 #else
340 *Marker = (VA_LIST) (DebugInfo + 1);
341 *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
342 return TRUE;
343 #endif
344 }
345