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