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