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