2 Library that helps implement monolithic PEI
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/ReportStatusCodeLib.h>
12 #include <Library/SerialPortLib.h>
13 #include <Library/PrintLib.h>
15 #include <Protocol/StatusCode.h>
16 #include <Guid/StatusCodeDataTypeId.h>
17 #include <Guid/StatusCodeDataTypeDebug.h>
21 SerialReportStatusCode (
22 IN EFI_STATUS_CODE_TYPE CodeType
,
23 IN EFI_STATUS_CODE_VALUE Value
,
25 IN CONST EFI_GUID
*CallerId
,
26 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
30 EFI_STATUS_CODE_PROTOCOL gStatusCode
= {
31 (EFI_REPORT_STATUS_CODE
)SerialReportStatusCode
35 Extracts ASSERT() information from a status code structure.
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.
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().
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().
60 @retval TRUE The status code specified by CodeType, Value, and Data was
61 converted ASSERT() arguments specified by Filename, Description,
63 @retval FALSE The status code specified by CodeType, Value, and Data could
64 not be converted to ASSERT() arguments.
69 ReportStatusCodeExtractAssertInfo (
70 IN EFI_STATUS_CODE_TYPE CodeType
,
71 IN EFI_STATUS_CODE_VALUE Value
,
72 IN CONST EFI_STATUS_CODE_DATA
*Data
,
74 OUT CHAR8
**Description
,
75 OUT UINT32
*LineNumber
78 EFI_DEBUG_ASSERT_DATA
*AssertData
;
80 ASSERT (Data
!= NULL
);
81 ASSERT (Filename
!= NULL
);
82 ASSERT (Description
!= NULL
);
83 ASSERT (LineNumber
!= NULL
);
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
;
99 Extracts DEBUG() information from a status code structure.
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.
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().
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
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
129 ReportStatusCodeExtractDebugInfo (
130 IN CONST EFI_STATUS_CODE_DATA
*Data
,
131 OUT UINT32
*ErrorLevel
,
132 OUT BASE_LIST
*Marker
,
136 EFI_DEBUG_INFO
*DebugInfo
;
138 ASSERT (Data
!= NULL
);
139 ASSERT (ErrorLevel
!= NULL
);
140 ASSERT (Marker
!= NULL
);
141 ASSERT (Format
!= NULL
);
144 // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
146 if (!CompareGuid (&Data
->Type
, &gEfiStatusCodeDataTypeDebugGuid
)) {
151 // Retrieve the debug information from the status code record
153 DebugInfo
= (EFI_DEBUG_INFO
*)(Data
+ 1);
155 *ErrorLevel
= DebugInfo
->ErrorLevel
;
158 // The first 12 * UINTN bytes of the string are really an
159 // argument stack to support varargs on the Format string.
161 *Marker
= (BASE_LIST
) (DebugInfo
+ 1);
162 *Format
= (CHAR8
*)(((UINT64
*)*Marker
) + 12);
172 SerialReportStatusCode (
173 IN EFI_STATUS_CODE_TYPE CodeType
,
174 IN EFI_STATUS_CODE_VALUE Value
,
176 IN CONST EFI_GUID
*CallerId
,
177 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
183 CHAR8 Buffer
[EFI_STATUS_CODE_DATA_MAX_SIZE
];
188 EFI_DEBUG_INFO
*DebugInfo
;
194 ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
197 // Print ASSERT() information into output buffer.
199 CharCount
= AsciiSPrint (
201 EFI_STATUS_CODE_DATA_MAX_SIZE
,
202 "\n\rASSERT!: %a (%d): %a\n\r",
210 // Callout to standard output.
212 SerialPortWrite ((UINT8
*)Buffer
, CharCount
);
215 } else if (Data
!= NULL
&&
216 ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
219 // Print DEBUG() information into output buffer.
221 CharCount
= AsciiBSPrint (
223 EFI_STATUS_CODE_DATA_MAX_SIZE
,
228 } else if (Data
!= NULL
&&
229 CompareGuid (&Data
->Type
, &gEfiStatusCodeSpecificDataGuid
) &&
230 (CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_DEBUG_CODE
) {
233 // Print specific data into output buffer.
235 DebugInfo
= (EFI_DEBUG_INFO
*) (Data
+ 1);
236 Marker
= (BASE_LIST
) (DebugInfo
+ 1);
237 Format
= (CHAR8
*) (((UINT64
*) (DebugInfo
+ 1)) + 12);
239 CharCount
= AsciiBSPrint (Buffer
, EFI_STATUS_CODE_DATA_MAX_SIZE
, Format
, Marker
);
241 } else if ((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_ERROR_CODE
) {
243 // Print ERROR information into output buffer.
246 CharCount
= AsciiSPrint (
248 EFI_STATUS_CODE_DATA_MAX_SIZE
,
249 "ERROR: C%x:V%x I%x",
256 // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.
258 if (CallerId
!= NULL
) {
259 CharCount
+= AsciiSPrint (
260 &Buffer
[CharCount
- 1],
261 (EFI_STATUS_CODE_DATA_MAX_SIZE
- (sizeof (Buffer
[0]) * CharCount
)),
268 CharCount
+= AsciiSPrint (
269 &Buffer
[CharCount
- 1],
270 (EFI_STATUS_CODE_DATA_MAX_SIZE
- (sizeof (Buffer
[0]) * CharCount
)),
278 CharCount
+= AsciiSPrint (
279 &Buffer
[CharCount
- 1],
280 (EFI_STATUS_CODE_DATA_MAX_SIZE
- (sizeof (Buffer
[0]) * CharCount
)),
284 } else if ((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_PROGRESS_CODE
) {
285 CharCount
= AsciiSPrint (
287 EFI_STATUS_CODE_DATA_MAX_SIZE
,
288 "PROGRESS CODE: V%x I%x\n\r",
293 CharCount
= AsciiSPrint (
295 EFI_STATUS_CODE_DATA_MAX_SIZE
,
296 "Undefined: C%x:V%x I%x\n\r",
304 SerialPortWrite ((UINT8
*)Buffer
, CharCount
);
312 AddDxeCoreReportStatusCodeCallback (
316 BuildGuidDataHob (&gEfiStatusCodeRuntimeProtocolGuid
, &gStatusCode
, sizeof(VOID
*));