]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/PeiDebugLibDebugPpi/DebugLib.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Library / PeiDebugLibDebugPpi / DebugLib.c
1 /** @file
2 PEI debug lib instance base on gEdkiiDebugPpiGuid to save PEIM size.
3
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <PiPei.h>
11 #include <Ppi/Debug.h>
12 #include <Library/DebugLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/PeiServicesLib.h>
16 #include <Library/DebugPrintErrorLevelLib.h>
17 #include <Library/BaseLib.h>
18
19 /**
20 Prints a debug message to the debug output device if the specified
21 error level is enabled.
22
23 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
24 GetDebugPrintErrorLevel (), then print the message specified by Format and
25 the associated variable argument list to the debug output device.
26
27 If Format is NULL, then ASSERT().
28
29 @param ErrorLevel The error level of the debug message.
30 @param Format Format string for the debug message to print.
31 @param ... Variable argument list whose contents are accessed
32 based on the format string specified by Format.
33
34 **/
35 VOID
36 EFIAPI
37 DebugPrint (
38 IN UINTN ErrorLevel,
39 IN CONST CHAR8 *Format,
40 ...
41 )
42 {
43 VA_LIST Marker;
44
45 VA_START (Marker, Format);
46 DebugVPrint (ErrorLevel, Format, Marker);
47 VA_END (Marker);
48 }
49
50 /**
51 Prints a debug message to the debug output device if the specified
52 error level is enabled.
53 This function use BASE_LIST which would provide a more compatible
54 service than VA_LIST.
55
56 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
57 GetDebugPrintErrorLevel (), then print the message specified by Format and
58 the associated variable argument list to the debug output device.
59
60 If Format is NULL, then ASSERT().
61
62 @param ErrorLevel The error level of the debug message.
63 @param Format Format string for the debug message to print.
64 @param BaseListMarker BASE_LIST marker for the variable argument list.
65
66 **/
67 VOID
68 EFIAPI
69 DebugBPrint (
70 IN UINTN ErrorLevel,
71 IN CONST CHAR8 *Format,
72 IN BASE_LIST BaseListMarker
73 )
74 {
75 EFI_STATUS Status;
76 EDKII_DEBUG_PPI *DebugPpi;
77
78 //
79 // If Format is NULL, then ASSERT().
80 //
81 ASSERT (Format != NULL);
82
83 //
84 // Check driver Debug Level value and global debug level
85 //
86 if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
87 return;
88 }
89
90 Status = PeiServicesLocatePpi (
91 &gEdkiiDebugPpiGuid,
92 0,
93 NULL,
94 (VOID **)&DebugPpi
95 );
96 if (EFI_ERROR (Status)) {
97 return;
98 }
99
100 DebugPpi->DebugBPrint (
101 ErrorLevel,
102 Format,
103 BaseListMarker
104 );
105 }
106
107 /**
108 Worker function that convert a VA_LIST to a BASE_LIST based on a
109 Null-terminated format string.
110
111 @param Format Null-terminated format string.
112 @param VaListMarker VA_LIST style variable argument list consumed
113 by processing Format.
114 @param BaseListMarker BASE_LIST style variable argument list consumed
115 by processing Format.
116 @param Size The size, in bytes, of the BaseListMarker buffer.
117
118 @return TRUE The VA_LIST has been converted to BASE_LIST.
119 @return FALSE The VA_LIST has not been converted to BASE_LIST.
120
121 **/
122 BOOLEAN
123 VaListToBaseList (
124 IN CONST CHAR8 *Format,
125 IN VA_LIST VaListMarker,
126 OUT BASE_LIST BaseListMarker,
127 IN UINTN Size
128 )
129 {
130 BASE_LIST BaseListStart;
131 BOOLEAN Long;
132
133 ASSERT (Format != NULL);
134
135 ASSERT (BaseListMarker != NULL);
136
137 BaseListStart = BaseListMarker;
138
139 for ( ; *Format != '\0'; Format++) {
140 //
141 // Only format with prefix % is processed.
142 //
143 if (*Format != '%') {
144 continue;
145 }
146
147 Long = FALSE;
148
149 //
150 // Parse Flags and Width
151 //
152 for (Format++; TRUE; Format++) {
153 if ((*Format == '.') || (*Format == '-') || (*Format == '+') || (*Format == ' ')) {
154 //
155 // These characters in format field are omitted.
156 //
157 continue;
158 }
159
160 if ((*Format >= '0') && (*Format <= '9')) {
161 //
162 // These characters in format field are omitted.
163 //
164 continue;
165 }
166
167 if ((*Format == 'L') || (*Format == 'l')) {
168 //
169 // 'L" or "l" in format field means the number being printed is a UINT64
170 //
171 Long = TRUE;
172 continue;
173 }
174
175 if (*Format == '*') {
176 //
177 // '*' in format field means the precision of the field is specified by
178 // a UINTN argument in the argument list.
179 //
180 BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);
181 continue;
182 }
183
184 if (*Format == '\0') {
185 //
186 // Make no output if Format string terminates unexpectedly when
187 // looking up for flag, width, precision and type.
188 //
189 Format--;
190 }
191
192 //
193 // When valid argument type detected or format string terminates unexpectedly,
194 // the inner loop is done.
195 //
196 break;
197 }
198
199 //
200 // Pack variable arguments into the storage area following EFI_DEBUG_INFO.
201 //
202 if ((*Format == 'p') && (sizeof (VOID *) > 4)) {
203 Long = TRUE;
204 }
205
206 if ((*Format == 'p') || (*Format == 'X') || (*Format == 'x') || (*Format == 'd') || (*Format == 'u')) {
207 if (Long) {
208 BASE_ARG (BaseListMarker, INT64) = VA_ARG (VaListMarker, INT64);
209 } else {
210 BASE_ARG (BaseListMarker, int) = VA_ARG (VaListMarker, int);
211 }
212 } else if ((*Format == 's') || (*Format == 'S') || (*Format == 'a') || (*Format == 'g') || (*Format == 't')) {
213 BASE_ARG (BaseListMarker, VOID *) = VA_ARG (VaListMarker, VOID *);
214 } else if (*Format == 'c') {
215 BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);
216 } else if (*Format == 'r') {
217 BASE_ARG (BaseListMarker, RETURN_STATUS) = VA_ARG (VaListMarker, RETURN_STATUS);
218 }
219
220 //
221 // If the converted BASE_LIST is larger than the size of BaseListMarker, then return FALSE
222 //
223 if (((UINTN)BaseListMarker - (UINTN)BaseListStart) > Size) {
224 return FALSE;
225 }
226 }
227
228 return TRUE;
229 }
230
231 /**
232 Prints a debug message to the debug output device if the specified
233 error level is enabled.
234
235 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
236 GetDebugPrintErrorLevel (), then print the message specified by Format and
237 the associated variable argument list to the debug output device.
238
239 If Format is NULL, then ASSERT().
240
241 @param ErrorLevel The error level of the debug message.
242 @param Format Format string for the debug message to print.
243 @param VaListMarker VA_LIST marker for the variable argument list.
244
245 **/
246 VOID
247 EFIAPI
248 DebugVPrint (
249 IN UINTN ErrorLevel,
250 IN CONST CHAR8 *Format,
251 IN VA_LIST VaListMarker
252 )
253 {
254 UINT64 BaseListMarker[256 / sizeof (UINT64)];
255 BOOLEAN Converted;
256
257 //
258 // Convert the VaList to BaseList
259 //
260 Converted = VaListToBaseList (
261 Format,
262 VaListMarker,
263 (BASE_LIST)BaseListMarker,
264 sizeof (BaseListMarker) - 8
265 );
266
267 if (!Converted) {
268 return;
269 }
270
271 DebugBPrint (ErrorLevel, Format, (BASE_LIST)BaseListMarker);
272 }
273
274 /**
275 Prints an assert message containing a filename, line number, and description.
276 This may be followed by a breakpoint or a dead loop.
277
278 Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
279 to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
280 PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
281 DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
282 CpuDeadLoop() is called. If neither of these bits are set, then this function
283 returns immediately after the message is printed to the debug output device.
284 DebugAssert() must actively prevent recursion. If DebugAssert() is called while
285 processing another DebugAssert(), then DebugAssert() must return immediately.
286
287 If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
288 If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
289
290 @param FileName The pointer to the name of the source file that generated the assert condition.
291 @param LineNumber The line number in the source file that generated the assert condition
292 @param Description The pointer to the description of the assert condition.
293
294 **/
295 VOID
296 EFIAPI
297 DebugAssert (
298 IN CONST CHAR8 *FileName,
299 IN UINTN LineNumber,
300 IN CONST CHAR8 *Description
301 )
302 {
303 EFI_STATUS Status;
304 EDKII_DEBUG_PPI *DebugPpi;
305
306 Status = PeiServicesLocatePpi (
307 &gEdkiiDebugPpiGuid,
308 0,
309 NULL,
310 (VOID **)&DebugPpi
311 );
312 if (EFI_ERROR (Status)) {
313 //
314 // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
315 //
316 if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
317 CpuBreakpoint ();
318 } else if ((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
319 CpuDeadLoop ();
320 }
321 } else {
322 DebugPpi->DebugAssert (
323 FileName,
324 LineNumber,
325 Description
326 );
327 }
328 }
329
330 /**
331 Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
332
333 This function fills Length bytes of Buffer with the value specified by
334 PcdDebugClearMemoryValue, and returns Buffer.
335
336 If Buffer is NULL, then ASSERT().
337 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
338
339 @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
340 @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
341
342 @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue.
343
344 **/
345 VOID *
346 EFIAPI
347 DebugClearMemory (
348 OUT VOID *Buffer,
349 IN UINTN Length
350 )
351 {
352 ASSERT (Buffer != NULL);
353
354 return SetMem (Buffer, Length, PcdGet8 (PcdDebugClearMemoryValue));
355 }
356
357 /**
358 Returns TRUE if ASSERT() macros are enabled.
359
360 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
361 PcdDebugProperyMask is set. Otherwise, FALSE is returned.
362
363 @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
364 @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
365
366 **/
367 BOOLEAN
368 EFIAPI
369 DebugAssertEnabled (
370 VOID
371 )
372 {
373 return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
374 }
375
376 /**
377 Returns TRUE if DEBUG() macros are enabled.
378
379 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
380 PcdDebugProperyMask is set. Otherwise, FALSE is returned.
381
382 @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
383 @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
384
385 **/
386 BOOLEAN
387 EFIAPI
388 DebugPrintEnabled (
389 VOID
390 )
391 {
392 return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
393 }
394
395 /**
396 Returns TRUE if DEBUG_CODE() macros are enabled.
397
398 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
399 PcdDebugProperyMask is set. Otherwise, FALSE is returned.
400
401 @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
402 @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
403
404 **/
405 BOOLEAN
406 EFIAPI
407 DebugCodeEnabled (
408 VOID
409 )
410 {
411 return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
412 }
413
414 /**
415 Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
416
417 This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
418 PcdDebugProperyMask is set. Otherwise, FALSE is returned.
419
420 @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
421 @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
422
423 **/
424 BOOLEAN
425 EFIAPI
426 DebugClearMemoryEnabled (
427 VOID
428 )
429 {
430 return (BOOLEAN)((PcdGet8 (PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
431 }
432
433 /**
434 Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.
435
436 This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.
437
438 @retval TRUE Current ErrorLevel is supported.
439 @retval FALSE Current ErrorLevel is not supported.
440
441 **/
442 BOOLEAN
443 EFIAPI
444 DebugPrintLevelEnabled (
445 IN CONST UINTN ErrorLevel
446 )
447 {
448 return (BOOLEAN)((ErrorLevel & PcdGet32 (PcdFixedDebugPrintErrorLevel)) != 0);
449 }