]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c
Remove extra #includes where possible to make build more efficient
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / PeiDxeDebugLibReportStatusCode / DebugLib.c
1 /** @file
2 Debug Library based on report status code library.
3
4 Copyright (c) 2006 - 2009, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <FrameworkPei.h>
16
17 #include <Guid/StatusCodeDataTypeId.h>
18 #include <Guid/StatusCodeDataTypeDebug.h>
19
20 #include <Library/DebugLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/ReportStatusCodeLib.h>
24 #include <Library/PcdLib.h>
25
26 /**
27 Prints a debug message to the debug output device if the specified error level is enabled.
28
29 If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print
30 the message specified by Format and the associated variable argument list to
31 the debug output device.
32
33 If Format is NULL, then ASSERT().
34
35 @param ErrorLevel The error level of the debug message.
36 @param Format Format string for the debug message to print.
37 @param ... Variable argument list whose contents are accessed
38 based on the format string specified by Format.
39
40 **/
41 VOID
42 EFIAPI
43 DebugPrint (
44 IN UINTN ErrorLevel,
45 IN CONST CHAR8 *Format,
46 ...
47 )
48 {
49 UINT64 Buffer[(EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof (UINT64)) + 1];
50 EFI_DEBUG_INFO *DebugInfo;
51 UINTN TotalSize;
52 VA_LIST VaListMarker;
53 BASE_LIST BaseListMarker;
54 CHAR8 *FormatString;
55 BOOLEAN Long;
56 BOOLEAN Done;
57
58 //
59 // If Format is NULL, then ASSERT().
60 //
61 ASSERT (Format != NULL);
62
63 //
64 // Check driver Debug Level value and global debug level
65 //
66 if ((ErrorLevel & PcdGet32 (PcdDebugPrintErrorLevel)) == 0) {
67 return;
68 }
69
70 //
71 // Compute the total size of the record
72 //
73 TotalSize = sizeof (EFI_DEBUG_INFO) + 12 * sizeof (UINT64) + AsciiStrSize (Format);
74
75 //
76 // If the TotalSize is larger than the maximum record size, then return
77 //
78 if (TotalSize > sizeof (Buffer)) {
79 return;
80 }
81
82 //
83 // Fill in EFI_DEBUG_INFO
84 //
85 // Here we skip the first 4 bytes of Buffer, because we must ensure BaseListMarker is
86 // 64-bit aligned, otherwise retrieving 64-bit parameter from BaseListMarker will cause
87 // exception on IPF. Buffer starts at 64-bit aligned address, so skipping 4 types (sizeof(EFI_DEBUG_INFO))
88 // just makes addess of BaseListMarker, which follows DebugInfo, 64-bit aligned.
89 //
90 DebugInfo = (EFI_DEBUG_INFO *)(Buffer) + 1;
91 DebugInfo->ErrorLevel = (UINT32)ErrorLevel;
92 BaseListMarker = (BASE_LIST)(DebugInfo + 1);
93 FormatString = (CHAR8 *)((UINT64 *)(DebugInfo + 1) + 12);
94
95 //
96 // Copy the Format string into the record
97 //
98 AsciiStrCpy (FormatString, Format);
99
100 //
101 // The first 12 * sizeof (UINT64) bytes following EFI_DEBUG_INFO are for variable arguments
102 // of format in DEBUG string, which is followed by the DEBUG format string.
103 // Here we will process the variable arguments and pack them in this area.
104 //
105 VA_START (VaListMarker, Format);
106 for (; *Format != '\0'; Format++) {
107 //
108 // Only format with prefix % is processed.
109 //
110 if (*Format != '%') {
111 continue;
112 }
113 Long = FALSE;
114 //
115 // Parse Flags and Width
116 //
117 for (Done = FALSE; !Done; ) {
118 Format++;
119 switch (*Format) {
120 case '.':
121 case '-':
122 case '+':
123 case ' ':
124 case ',':
125 case '0':
126 case '1':
127 case '2':
128 case '3':
129 case '4':
130 case '5':
131 case '6':
132 case '7':
133 case '8':
134 case '9':
135 //
136 // These characters in format field are omitted.
137 //
138 break;
139 case 'L':
140 case 'l':
141 //
142 // 'L" or "l" in format field means the number being printed is a UINT64
143 //
144 Long = TRUE;
145 break;
146 case '*':
147 //
148 // '*' in format field means the precision of the field is specified by
149 // a UINTN argument in the argument list.
150 //
151 BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);
152 break;
153 case '\0':
154 //
155 // Make no output if Format string terminates unexpectedly when
156 // looking up for flag, width, precision and type.
157 //
158 Format--;
159 //
160 // break skipped on purpose.
161 //
162 default:
163 //
164 // When valid argument type detected or format string terminates unexpectedly,
165 // the inner loop is done.
166 //
167 Done = TRUE;
168 break;
169 }
170 }
171
172 //
173 // Pack variable arguments into the storage area following EFI_DEBUG_INFO.
174 //
175 switch (*Format) {
176 case 'p':
177 if (sizeof (VOID *) > 4) {
178 Long = TRUE;
179 }
180 case 'X':
181 case 'x':
182 case 'd':
183 if (Long) {
184 BASE_ARG (BaseListMarker, INT64) = VA_ARG (VaListMarker, INT64);
185 } else {
186 BASE_ARG (BaseListMarker, int) = VA_ARG (VaListMarker, int);
187 }
188 break;
189 case 's':
190 case 'S':
191 case 'a':
192 case 'g':
193 case 't':
194 BASE_ARG (BaseListMarker, VOID *) = VA_ARG (VaListMarker, VOID *);
195 break;
196 case 'c':
197 BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);
198 break;
199 case 'r':
200 BASE_ARG (BaseListMarker, RETURN_STATUS) = VA_ARG (VaListMarker, RETURN_STATUS);
201 break;
202 }
203
204 //
205 // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then ASSERT()
206 // This indicates that the DEBUG() macro is passing in more argument than can be handled by
207 // the EFI_DEBUG_INFO record
208 //
209 ASSERT ((CHAR8 *)BaseListMarker <= FormatString);
210
211 //
212 // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then return
213 //
214 if ((CHAR8 *)BaseListMarker > FormatString) {
215 return;
216 }
217 }
218 VA_END (VaListMarker);
219
220 //
221 // Send the DebugInfo record
222 //
223 REPORT_STATUS_CODE_EX (
224 EFI_DEBUG_CODE,
225 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED),
226 0,
227 NULL,
228 &gEfiStatusCodeDataTypeDebugGuid,
229 DebugInfo,
230 TotalSize
231 );
232 }
233
234 /**
235 Prints an assert message containing a filename, line number, and description.
236 This may be followed by a breakpoint or a dead loop.
237
238 Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
239 to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
240 PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
241 DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
242 CpuDeadLoop() is called. If neither of these bits are set, then this function
243 returns immediately after the message is printed to the debug output device.
244 DebugAssert() must actively prevent recursion. If DebugAssert() is called while
245 processing another DebugAssert(), then DebugAssert() must return immediately.
246
247 If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
248 If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
249
250 @param FileName Pointer to the name of the source file that generated the assert condition.
251 @param LineNumber The line number in the source file that generated the assert condition
252 @param Description Pointer to the description of the assert condition.
253
254 **/
255 VOID
256 EFIAPI
257 DebugAssert (
258 IN CONST CHAR8 *FileName,
259 IN UINTN LineNumber,
260 IN CONST CHAR8 *Description
261 )
262 {
263 UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof(UINT64)];
264 EFI_DEBUG_ASSERT_DATA *AssertData;
265 UINTN TotalSize;
266 CHAR8 *Temp;
267 UINTN FileNameSize;
268 UINTN DescriptionSize;
269
270 //
271 // Make sure it will all fit in the passed in buffer
272 //
273 FileNameSize = AsciiStrSize (FileName);
274 DescriptionSize = AsciiStrSize (Description);
275 TotalSize = sizeof (EFI_DEBUG_ASSERT_DATA) + FileNameSize + DescriptionSize;
276 if (TotalSize <= sizeof (Buffer)) {
277 //
278 // Fill in EFI_DEBUG_ASSERT_DATA
279 //
280 AssertData = (EFI_DEBUG_ASSERT_DATA *)Buffer;
281 AssertData->LineNumber = (UINT32)LineNumber;
282
283 //
284 // Copy Ascii FileName including NULL.
285 //
286 Temp = AsciiStrCpy ((CHAR8 *)(AssertData + 1), FileName);
287
288 //
289 // Copy Ascii Description
290 //
291 AsciiStrCpy (Temp + FileNameSize, Description);
292
293 REPORT_STATUS_CODE_EX (
294 (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
295 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE),
296 0,
297 NULL,
298 NULL,
299 AssertData,
300 TotalSize
301 );
302 }
303
304 //
305 // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
306 //
307 if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
308 CpuBreakpoint ();
309 } else if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
310 CpuDeadLoop ();
311 }
312 }
313
314
315 /**
316 Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
317
318 This function fills Length bytes of Buffer with the value specified by
319 PcdDebugClearMemoryValue, and returns Buffer.
320
321 If Buffer is NULL, then ASSERT().
322 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
323
324 @param Buffer Pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
325 @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
326
327 @return Buffer Pointer to the target buffer filled with PcdDebugClearMemoryValue.
328
329 **/
330 VOID *
331 EFIAPI
332 DebugClearMemory (
333 OUT VOID *Buffer,
334 IN UINTN Length
335 )
336 {
337 ASSERT (Buffer != NULL);
338
339 return SetMem (Buffer, Length, PcdGet8 (PcdDebugClearMemoryValue));
340 }
341
342
343 /**
344 Returns TRUE if ASSERT() macros are enabled.
345
346 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
347 PcdDebugProperyMask is set. Otherwise FALSE is returned.
348
349 @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
350 @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
351
352 **/
353 BOOLEAN
354 EFIAPI
355 DebugAssertEnabled (
356 VOID
357 )
358 {
359 return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
360 }
361
362
363 /**
364 Returns TRUE if DEBUG() macros are enabled.
365
366 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
367 PcdDebugProperyMask is set. Otherwise FALSE is returned.
368
369 @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
370 @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
371
372 **/
373 BOOLEAN
374 EFIAPI
375 DebugPrintEnabled (
376 VOID
377 )
378 {
379 return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
380 }
381
382
383 /**
384 Returns TRUE if DEBUG_CODE() macros are enabled.
385
386 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
387 PcdDebugProperyMask is set. Otherwise FALSE is returned.
388
389 @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
390 @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
391
392 **/
393 BOOLEAN
394 EFIAPI
395 DebugCodeEnabled (
396 VOID
397 )
398 {
399 return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
400 }
401
402
403 /**
404 Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
405
406 This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
407 PcdDebugProperyMask is set. Otherwise FALSE is returned.
408
409 @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
410 @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
411
412 **/
413 BOOLEAN
414 EFIAPI
415 DebugClearMemoryEnabled (
416 VOID
417 )
418 {
419 return (BOOLEAN) ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
420 }