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