2 Library that helps implement monolithic PEI
4 Copyright (c) 2008-2009, Apple Inc. All rights reserved.
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/ReportStatusCodeLib.h>
18 #include <Library/SerialPortLib.h>
19 #include <Library/PrintLib.h>
21 #include <Protocol/StatusCode.h>
22 #include <Guid/StatusCodeDataTypeId.h>
23 #include <Guid/StatusCodeDataTypeDebug.h>
24 #include <FrameworkPei.h>
26 #define EFI_STATUS_CODE_DATA_MAX_SIZE 200
30 SerialReportStatusCode (
31 IN EFI_STATUS_CODE_TYPE CodeType
,
32 IN EFI_STATUS_CODE_VALUE Value
,
34 IN CONST EFI_GUID
*CallerId
,
35 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
39 EFI_STATUS_CODE_PROTOCOL gStatusCode
= {
40 (EFI_REPORT_STATUS_CODE
)SerialReportStatusCode
44 Extracts ASSERT() information from a status code structure.
46 Converts the status code specified by CodeType, Value, and Data to the ASSERT()
47 arguments specified by Filename, Description, and LineNumber. If CodeType is
48 an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and
49 Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract
50 Filename, Description, and LineNumber from the optional data area of the
51 status code buffer specified by Data. The optional data area of Data contains
52 a Null-terminated ASCII string for the FileName, followed by a Null-terminated
53 ASCII string for the Description, followed by a 32-bit LineNumber. If the
54 ASSERT() information could be extracted from Data, then return TRUE.
55 Otherwise, FALSE is returned.
57 If Data is NULL, then ASSERT().
58 If Filename is NULL, then ASSERT().
59 If Description is NULL, then ASSERT().
60 If LineNumber is NULL, then ASSERT().
62 @param CodeType The type of status code being converted.
63 @param Value The status code value being converted.
64 @param Data Pointer to status code data buffer.
65 @param Filename Pointer to the source file name that generated the ASSERT().
66 @param Description Pointer to the description of the ASSERT().
67 @param LineNumber Pointer to source line number that generated the ASSERT().
69 @retval TRUE The status code specified by CodeType, Value, and Data was
70 converted ASSERT() arguments specified by Filename, Description,
72 @retval FALSE The status code specified by CodeType, Value, and Data could
73 not be converted to ASSERT() arguments.
78 ReportStatusCodeExtractAssertInfo (
79 IN EFI_STATUS_CODE_TYPE CodeType
,
80 IN EFI_STATUS_CODE_VALUE Value
,
81 IN CONST EFI_STATUS_CODE_DATA
*Data
,
83 OUT CHAR8
**Description
,
84 OUT UINT32
*LineNumber
87 EFI_DEBUG_ASSERT_DATA
*AssertData
;
89 ASSERT (Data
!= NULL
);
90 ASSERT (Filename
!= NULL
);
91 ASSERT (Description
!= NULL
);
92 ASSERT (LineNumber
!= NULL
);
94 if (((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_ERROR_CODE
) &&
95 ((CodeType
& EFI_STATUS_CODE_SEVERITY_MASK
) == EFI_ERROR_UNRECOVERED
) &&
96 ((Value
& EFI_STATUS_CODE_OPERATION_MASK
) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE
)) {
97 AssertData
= (EFI_DEBUG_ASSERT_DATA
*)(Data
+ 1);
98 *Filename
= (CHAR8
*)(AssertData
+ 1);
99 *Description
= *Filename
+ AsciiStrLen (*Filename
) + 1;
100 *LineNumber
= AssertData
->LineNumber
;
108 Extracts DEBUG() information from a status code structure.
110 Converts the status code specified by Data to the DEBUG() arguments specified
111 by ErrorLevel, Marker, and Format. If type GUID in Data is
112 EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and
113 Format from the optional data area of the status code buffer specified by Data.
114 The optional data area of Data contains a 32-bit ErrorLevel followed by Marker
115 which is 12 UINTN parameters, followed by a Null-terminated ASCII string for
116 the Format. If the DEBUG() information could be extracted from Data, then
117 return TRUE. Otherwise, FALSE is returned.
119 If Data is NULL, then ASSERT().
120 If ErrorLevel is NULL, then ASSERT().
121 If Marker is NULL, then ASSERT().
122 If Format is NULL, then ASSERT().
124 @param Data Pointer to status code data buffer.
125 @param ErrorLevel Pointer to error level mask for a debug message.
126 @param Marker Pointer to the variable argument list associated with Format.
127 @param Format Pointer to a Null-terminated ASCII format string of a
130 @retval TRUE The status code specified by Data was converted DEBUG() arguments
131 specified by ErrorLevel, Marker, and Format.
132 @retval FALSE The status code specified by Data could not be converted to
138 ReportStatusCodeExtractDebugInfo (
139 IN CONST EFI_STATUS_CODE_DATA
*Data
,
140 OUT UINT32
*ErrorLevel
,
141 OUT BASE_LIST
*Marker
,
145 EFI_DEBUG_INFO
*DebugInfo
;
147 ASSERT (Data
!= NULL
);
148 ASSERT (ErrorLevel
!= NULL
);
149 ASSERT (Marker
!= NULL
);
150 ASSERT (Format
!= NULL
);
153 // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
155 if (!CompareGuid (&Data
->Type
, &gEfiStatusCodeDataTypeDebugGuid
)) {
160 // Retrieve the debug information from the status code record
162 DebugInfo
= (EFI_DEBUG_INFO
*)(Data
+ 1);
164 *ErrorLevel
= DebugInfo
->ErrorLevel
;
167 // The first 12 * UINTN bytes of the string are really an
168 // argument stack to support varargs on the Format string.
170 *Marker
= (BASE_LIST
) (DebugInfo
+ 1);
171 *Format
= (CHAR8
*)(((UINT64
*)*Marker
) + 12);
181 SerialReportStatusCode (
182 IN EFI_STATUS_CODE_TYPE CodeType
,
183 IN EFI_STATUS_CODE_VALUE Value
,
185 IN CONST EFI_GUID
*CallerId
,
186 IN CONST EFI_STATUS_CODE_DATA
*Data OPTIONAL
192 CHAR8 Buffer
[EFI_STATUS_CODE_DATA_MAX_SIZE
];
197 EFI_DEBUG_INFO
*DebugInfo
;
203 ReportStatusCodeExtractAssertInfo (CodeType
, Value
, Data
, &Filename
, &Description
, &LineNumber
)) {
206 // Print ASSERT() information into output buffer.
208 CharCount
= AsciiSPrint (
210 EFI_STATUS_CODE_DATA_MAX_SIZE
,
211 "\n\rASSERT!: %a (%d): %a\n\r",
219 // Callout to standard output.
221 SerialPortWrite ((UINT8
*)Buffer
, CharCount
);
224 } else if (Data
!= NULL
&&
225 ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
228 // Print DEBUG() information into output buffer.
230 CharCount
= AsciiBSPrint (
232 EFI_STATUS_CODE_DATA_MAX_SIZE
,
237 } else if (Data
!= NULL
&&
238 CompareGuid (&Data
->Type
, &gEfiStatusCodeSpecificDataGuid
) &&
239 (CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_DEBUG_CODE
) {
242 // Print specific data into output buffer.
244 DebugInfo
= (EFI_DEBUG_INFO
*) (Data
+ 1);
245 Marker
= (BASE_LIST
) (DebugInfo
+ 1);
246 Format
= (CHAR8
*) (((UINT64
*) (DebugInfo
+ 1)) + 12);
248 CharCount
= AsciiBSPrint (Buffer
, EFI_STATUS_CODE_DATA_MAX_SIZE
, Format
, Marker
);
250 } else if ((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_ERROR_CODE
) {
252 // Print ERROR information into output buffer.
255 CharCount
= AsciiSPrint (
257 EFI_STATUS_CODE_DATA_MAX_SIZE
,
258 "ERROR: C%x:V%x I%x",
265 // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.
267 if (CallerId
!= NULL
) {
268 CharCount
+= AsciiSPrint (
269 &Buffer
[CharCount
- 1],
270 (EFI_STATUS_CODE_DATA_MAX_SIZE
- (sizeof (Buffer
[0]) * CharCount
)),
277 CharCount
+= AsciiSPrint (
278 &Buffer
[CharCount
- 1],
279 (EFI_STATUS_CODE_DATA_MAX_SIZE
- (sizeof (Buffer
[0]) * CharCount
)),
287 CharCount
+= AsciiSPrint (
288 &Buffer
[CharCount
- 1],
289 (EFI_STATUS_CODE_DATA_MAX_SIZE
- (sizeof (Buffer
[0]) * CharCount
)),
293 } else if ((CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_PROGRESS_CODE
) {
294 CharCount
= AsciiSPrint (
296 EFI_STATUS_CODE_DATA_MAX_SIZE
,
297 "PROGRESS CODE: V%x I%x\n\r",
302 CharCount
= AsciiSPrint (
304 EFI_STATUS_CODE_DATA_MAX_SIZE
,
305 "Undefined: C%x:V%x I%x\n\r",
313 SerialPortWrite ((UINT8
*)Buffer
, CharCount
);
321 AddDxeCoreReportStatusCodeCallback (
325 BuildGuidDataHob (&gEfiStatusCodeRuntimeProtocolGuid
, &gStatusCode
, sizeof(VOID
*));