]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c
OvmfPkg/QemuVideoDxe: Shouldn't assume system in VGA alias mode.
[mirror_edk2.git] / EmbeddedPkg / Library / PrePiLib / ReportStatusCode.c
1 /** @file
2 Library that helps implement monolithic PEI
3
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <PrePi.h>
11 #include <Library/ReportStatusCodeLib.h>
12 #include <Library/SerialPortLib.h>
13 #include <Library/PrintLib.h>
14
15 #include <Protocol/StatusCode.h>
16 #include <Guid/StatusCodeDataTypeId.h>
17 #include <Guid/StatusCodeDataTypeDebug.h>
18
19 EFI_STATUS
20 EFIAPI
21 SerialReportStatusCode (
22 IN EFI_STATUS_CODE_TYPE CodeType,
23 IN EFI_STATUS_CODE_VALUE Value,
24 IN UINT32 Instance,
25 IN CONST EFI_GUID *CallerId,
26 IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
27 );
28
29
30 EFI_STATUS_CODE_PROTOCOL gStatusCode = {
31 (EFI_REPORT_STATUS_CODE)SerialReportStatusCode
32 };
33
34 /**
35 Extracts ASSERT() information from a status code structure.
36
37 Converts the status code specified by CodeType, Value, and Data to the ASSERT()
38 arguments specified by Filename, Description, and LineNumber. If CodeType is
39 an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and
40 Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract
41 Filename, Description, and LineNumber from the optional data area of the
42 status code buffer specified by Data. The optional data area of Data contains
43 a Null-terminated ASCII string for the FileName, followed by a Null-terminated
44 ASCII string for the Description, followed by a 32-bit LineNumber. If the
45 ASSERT() information could be extracted from Data, then return TRUE.
46 Otherwise, FALSE is returned.
47
48 If Data is NULL, then ASSERT().
49 If Filename is NULL, then ASSERT().
50 If Description is NULL, then ASSERT().
51 If LineNumber is NULL, then ASSERT().
52
53 @param CodeType The type of status code being converted.
54 @param Value The status code value being converted.
55 @param Data Pointer to status code data buffer.
56 @param Filename Pointer to the source file name that generated the ASSERT().
57 @param Description Pointer to the description of the ASSERT().
58 @param LineNumber Pointer to source line number that generated the ASSERT().
59
60 @retval TRUE The status code specified by CodeType, Value, and Data was
61 converted ASSERT() arguments specified by Filename, Description,
62 and LineNumber.
63 @retval FALSE The status code specified by CodeType, Value, and Data could
64 not be converted to ASSERT() arguments.
65
66 **/
67 BOOLEAN
68 EFIAPI
69 ReportStatusCodeExtractAssertInfo (
70 IN EFI_STATUS_CODE_TYPE CodeType,
71 IN EFI_STATUS_CODE_VALUE Value,
72 IN CONST EFI_STATUS_CODE_DATA *Data,
73 OUT CHAR8 **Filename,
74 OUT CHAR8 **Description,
75 OUT UINT32 *LineNumber
76 )
77 {
78 EFI_DEBUG_ASSERT_DATA *AssertData;
79
80 ASSERT (Data != NULL);
81 ASSERT (Filename != NULL);
82 ASSERT (Description != NULL);
83 ASSERT (LineNumber != NULL);
84
85 if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
86 ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) &&
87 ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) {
88 AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
89 *Filename = (CHAR8 *)(AssertData + 1);
90 *Description = *Filename + AsciiStrLen (*Filename) + 1;
91 *LineNumber = AssertData->LineNumber;
92 return TRUE;
93 }
94 return FALSE;
95 }
96
97
98 /**
99 Extracts DEBUG() information from a status code structure.
100
101 Converts the status code specified by Data to the DEBUG() arguments specified
102 by ErrorLevel, Marker, and Format. If type GUID in Data is
103 EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and
104 Format from the optional data area of the status code buffer specified by Data.
105 The optional data area of Data contains a 32-bit ErrorLevel followed by Marker
106 which is 12 UINTN parameters, followed by a Null-terminated ASCII string for
107 the Format. If the DEBUG() information could be extracted from Data, then
108 return TRUE. Otherwise, FALSE is returned.
109
110 If Data is NULL, then ASSERT().
111 If ErrorLevel is NULL, then ASSERT().
112 If Marker is NULL, then ASSERT().
113 If Format is NULL, then ASSERT().
114
115 @param Data Pointer to status code data buffer.
116 @param ErrorLevel Pointer to error level mask for a debug message.
117 @param Marker Pointer to the variable argument list associated with Format.
118 @param Format Pointer to a Null-terminated ASCII format string of a
119 debug message.
120
121 @retval TRUE The status code specified by Data was converted DEBUG() arguments
122 specified by ErrorLevel, Marker, and Format.
123 @retval FALSE The status code specified by Data could not be converted to
124 DEBUG() arguments.
125
126 **/
127 BOOLEAN
128 EFIAPI
129 ReportStatusCodeExtractDebugInfo (
130 IN CONST EFI_STATUS_CODE_DATA *Data,
131 OUT UINT32 *ErrorLevel,
132 OUT BASE_LIST *Marker,
133 OUT CHAR8 **Format
134 )
135 {
136 EFI_DEBUG_INFO *DebugInfo;
137
138 ASSERT (Data != NULL);
139 ASSERT (ErrorLevel != NULL);
140 ASSERT (Marker != NULL);
141 ASSERT (Format != NULL);
142
143 //
144 // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
145 //
146 if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) {
147 return FALSE;
148 }
149
150 //
151 // Retrieve the debug information from the status code record
152 //
153 DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
154
155 *ErrorLevel = DebugInfo->ErrorLevel;
156
157 //
158 // The first 12 * UINTN bytes of the string are really an
159 // argument stack to support varargs on the Format string.
160 //
161 *Marker = (BASE_LIST) (DebugInfo + 1);
162 *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
163
164 return TRUE;
165 }
166
167
168
169
170 EFI_STATUS
171 EFIAPI
172 SerialReportStatusCode (
173 IN EFI_STATUS_CODE_TYPE CodeType,
174 IN EFI_STATUS_CODE_VALUE Value,
175 IN UINT32 Instance,
176 IN CONST EFI_GUID *CallerId,
177 IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
178 )
179 {
180 CHAR8 *Filename;
181 CHAR8 *Description;
182 CHAR8 *Format;
183 CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
184 UINT32 ErrorLevel;
185 UINT32 LineNumber;
186 UINTN CharCount;
187 BASE_LIST Marker;
188 EFI_DEBUG_INFO *DebugInfo;
189
190 Buffer[0] = '\0';
191
192
193 if (Data != NULL &&
194 ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
195
196 //
197 // Print ASSERT() information into output buffer.
198 //
199 CharCount = AsciiSPrint (
200 Buffer,
201 EFI_STATUS_CODE_DATA_MAX_SIZE,
202 "\n\rASSERT!: %a (%d): %a\n\r",
203 Filename,
204 LineNumber,
205 Description
206 );
207
208
209 //
210 // Callout to standard output.
211 //
212 SerialPortWrite ((UINT8 *)Buffer, CharCount);
213 return EFI_SUCCESS;
214
215 } else if (Data != NULL &&
216 ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
217
218 //
219 // Print DEBUG() information into output buffer.
220 //
221 CharCount = AsciiBSPrint (
222 Buffer,
223 EFI_STATUS_CODE_DATA_MAX_SIZE,
224 Format,
225 Marker
226 );
227
228 } else if (Data != NULL &&
229 CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) &&
230 (CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
231
232 //
233 // Print specific data into output buffer.
234 //
235 DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
236 Marker = (BASE_LIST) (DebugInfo + 1);
237 Format = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12);
238
239 CharCount = AsciiBSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker);
240
241 } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
242 //
243 // Print ERROR information into output buffer.
244 //
245
246 CharCount = AsciiSPrint (
247 Buffer,
248 EFI_STATUS_CODE_DATA_MAX_SIZE,
249 "ERROR: C%x:V%x I%x",
250 CodeType,
251 Value,
252 Instance
253 );
254
255 //
256 // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.
257 //
258 if (CallerId != NULL) {
259 CharCount += AsciiSPrint (
260 &Buffer[CharCount - 1],
261 (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
262 " %g",
263 CallerId
264 );
265 }
266
267 if (Data != NULL) {
268 CharCount += AsciiSPrint (
269 &Buffer[CharCount - 1],
270 (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
271 " %x",
272 Data
273 );
274
275 }
276
277
278 CharCount += AsciiSPrint (
279 &Buffer[CharCount - 1],
280 (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
281 "\n\r"
282 );
283
284 } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
285 CharCount = AsciiSPrint (
286 Buffer,
287 EFI_STATUS_CODE_DATA_MAX_SIZE,
288 "PROGRESS CODE: V%x I%x\n\r",
289 Value,
290 Instance
291 );
292 } else {
293 CharCount = AsciiSPrint (
294 Buffer,
295 EFI_STATUS_CODE_DATA_MAX_SIZE,
296 "Undefined: C%x:V%x I%x\n\r",
297 CodeType,
298 Value,
299 Instance
300 );
301
302 }
303
304 SerialPortWrite ((UINT8 *)Buffer, CharCount);
305 return EFI_SUCCESS;
306
307 }
308
309
310 VOID
311 EFIAPI
312 AddDxeCoreReportStatusCodeCallback (
313 VOID
314 )
315 {
316 BuildGuidDataHob (&gEfiStatusCodeRuntimeProtocolGuid, &gStatusCode, sizeof(VOID *));
317 }
318