]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c
Add the beginning of a GDB based Debug Agent. IA-32 and X64 don't have low level...
[mirror_edk2.git] / EmbeddedPkg / Library / PrePiLib / ReportStatusCode.c
1 /** @file
2 Library that helps implement monolithic PEI
3
4 Copyright (c) 2008-2009, Apple Inc. All rights reserved.
5
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
10
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.
13
14 **/
15
16 #include <PrePi.h>
17 #include <Library/ReportStatusCodeLib.h>
18 #include <Library/SerialPortLib.h>
19 #include <Library/PrintLib.h>
20
21 #include <Protocol/StatusCode.h>
22 #include <Guid/StatusCodeDataTypeId.h>
23 #include <Guid/StatusCodeDataTypeDebug.h>
24 #include <FrameworkPei.h>
25
26 #define EFI_STATUS_CODE_DATA_MAX_SIZE 200
27
28 EFI_STATUS
29 EFIAPI
30 SerialReportStatusCode (
31 IN EFI_STATUS_CODE_TYPE CodeType,
32 IN EFI_STATUS_CODE_VALUE Value,
33 IN UINT32 Instance,
34 IN CONST EFI_GUID *CallerId,
35 IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
36 );
37
38
39 EFI_STATUS_CODE_PROTOCOL gStatusCode = {
40 (EFI_REPORT_STATUS_CODE)SerialReportStatusCode
41 };
42
43 /**
44 Extracts ASSERT() information from a status code structure.
45
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.
56
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().
61
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().
68
69 @retval TRUE The status code specified by CodeType, Value, and Data was
70 converted ASSERT() arguments specified by Filename, Description,
71 and LineNumber.
72 @retval FALSE The status code specified by CodeType, Value, and Data could
73 not be converted to ASSERT() arguments.
74
75 **/
76 BOOLEAN
77 EFIAPI
78 ReportStatusCodeExtractAssertInfo (
79 IN EFI_STATUS_CODE_TYPE CodeType,
80 IN EFI_STATUS_CODE_VALUE Value,
81 IN CONST EFI_STATUS_CODE_DATA *Data,
82 OUT CHAR8 **Filename,
83 OUT CHAR8 **Description,
84 OUT UINT32 *LineNumber
85 )
86 {
87 EFI_DEBUG_ASSERT_DATA *AssertData;
88
89 ASSERT (Data != NULL);
90 ASSERT (Filename != NULL);
91 ASSERT (Description != NULL);
92 ASSERT (LineNumber != NULL);
93
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;
101 return TRUE;
102 }
103 return FALSE;
104 }
105
106
107 /**
108 Extracts DEBUG() information from a status code structure.
109
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.
118
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().
123
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
128 debug message.
129
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
133 DEBUG() arguments.
134
135 **/
136 BOOLEAN
137 EFIAPI
138 ReportStatusCodeExtractDebugInfo (
139 IN CONST EFI_STATUS_CODE_DATA *Data,
140 OUT UINT32 *ErrorLevel,
141 OUT BASE_LIST *Marker,
142 OUT CHAR8 **Format
143 )
144 {
145 EFI_DEBUG_INFO *DebugInfo;
146
147 ASSERT (Data != NULL);
148 ASSERT (ErrorLevel != NULL);
149 ASSERT (Marker != NULL);
150 ASSERT (Format != NULL);
151
152 //
153 // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
154 //
155 if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) {
156 return FALSE;
157 }
158
159 //
160 // Retrieve the debug information from the status code record
161 //
162 DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
163
164 *ErrorLevel = DebugInfo->ErrorLevel;
165
166 //
167 // The first 12 * UINTN bytes of the string are really an
168 // argument stack to support varargs on the Format string.
169 //
170 *Marker = (BASE_LIST) (DebugInfo + 1);
171 *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
172
173 return TRUE;
174 }
175
176
177
178
179 EFI_STATUS
180 EFIAPI
181 SerialReportStatusCode (
182 IN EFI_STATUS_CODE_TYPE CodeType,
183 IN EFI_STATUS_CODE_VALUE Value,
184 IN UINT32 Instance,
185 IN CONST EFI_GUID *CallerId,
186 IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
187 )
188 {
189 CHAR8 *Filename;
190 CHAR8 *Description;
191 CHAR8 *Format;
192 CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
193 UINT32 ErrorLevel;
194 UINT32 LineNumber;
195 UINTN CharCount;
196 BASE_LIST Marker;
197 EFI_DEBUG_INFO *DebugInfo;
198
199 Buffer[0] = '\0';
200
201
202 if (Data != NULL &&
203 ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
204
205 //
206 // Print ASSERT() information into output buffer.
207 //
208 CharCount = AsciiSPrint (
209 Buffer,
210 EFI_STATUS_CODE_DATA_MAX_SIZE,
211 "\n\rASSERT!: %a (%d): %a\n\r",
212 Filename,
213 LineNumber,
214 Description
215 );
216
217
218 //
219 // Callout to standard output.
220 //
221 SerialPortWrite ((UINT8 *)Buffer, CharCount);
222 return EFI_SUCCESS;
223
224 } else if (Data != NULL &&
225 ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
226
227 //
228 // Print DEBUG() information into output buffer.
229 //
230 CharCount = AsciiBSPrint (
231 Buffer,
232 EFI_STATUS_CODE_DATA_MAX_SIZE,
233 Format,
234 Marker
235 );
236
237 } else if (Data != NULL &&
238 CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) &&
239 (CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
240
241 //
242 // Print specific data into output buffer.
243 //
244 DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
245 Marker = (BASE_LIST) (DebugInfo + 1);
246 Format = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12);
247
248 CharCount = AsciiBSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker);
249
250 } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
251 //
252 // Print ERROR information into output buffer.
253 //
254
255 CharCount = AsciiSPrint (
256 Buffer,
257 EFI_STATUS_CODE_DATA_MAX_SIZE,
258 "ERROR: C%x:V%x I%x",
259 CodeType,
260 Value,
261 Instance
262 );
263
264 //
265 // Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.
266 //
267 if (CallerId != NULL) {
268 CharCount += AsciiSPrint (
269 &Buffer[CharCount - 1],
270 (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
271 " %g",
272 CallerId
273 );
274 }
275
276 if (Data != NULL) {
277 CharCount += AsciiSPrint (
278 &Buffer[CharCount - 1],
279 (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
280 " %x",
281 Data
282 );
283
284 }
285
286
287 CharCount += AsciiSPrint (
288 &Buffer[CharCount - 1],
289 (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
290 "\n\r"
291 );
292
293 } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
294 CharCount = AsciiSPrint (
295 Buffer,
296 EFI_STATUS_CODE_DATA_MAX_SIZE,
297 "PROGRESS CODE: V%x I%x\n\r",
298 Value,
299 Instance
300 );
301 } else {
302 CharCount = AsciiSPrint (
303 Buffer,
304 EFI_STATUS_CODE_DATA_MAX_SIZE,
305 "Undefined: C%x:V%x I%x\n\r",
306 CodeType,
307 Value,
308 Instance
309 );
310
311 }
312
313 SerialPortWrite ((UINT8 *)Buffer, CharCount);
314 return EFI_SUCCESS;
315
316 }
317
318
319 VOID
320 EFIAPI
321 AddDxeCoreReportStatusCodeCallback (
322 VOID
323 )
324 {
325 BuildGuidDataHob (&gEfiStatusCodeRuntimeProtocolGuid, &gStatusCode, sizeof(VOID *));
326 }
327