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