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