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