]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiDebugLibDebugPortProtocol/DebugLib.c
MdePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdePkg / Library / UefiDebugLibDebugPortProtocol / DebugLib.c
CommitLineData
b29910d6
MM
1/** @file\r
2 UEFI Debug Library that sends messages to EFI_DEBUGPORT_PROTOCOL.Write.\r
3\r
27d86bc1 4 Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>\r
9344f092 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
b29910d6
MM
6\r
7**/\r
8\r
9#include <Uefi.h>\r
10\r
11#include <Library/DebugLib.h>\r
12#include <Library/UefiBootServicesTableLib.h>\r
13#include <Library/PrintLib.h>\r
14#include <Library/PcdLib.h>\r
15#include <Library/BaseLib.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/DebugPrintErrorLevelLib.h>\r
18\r
19#include <Protocol/DebugPort.h>\r
20\r
21//\r
9095d37b 22// Define the maximum debug and assert message length that this library supports\r
b29910d6
MM
23//\r
24#define MAX_DEBUG_MESSAGE_LENGTH 0x100\r
25\r
26//\r
9095d37b 27// Define the timeout for EFI_DEBUGPORT_PROTOCOL.Write\r
b29910d6
MM
28//\r
29#define WRITE_TIMEOUT 1000\r
30\r
31\r
32EFI_DEBUGPORT_PROTOCOL *mDebugPort = NULL;\r
33\r
27d86bc1
BB
34//\r
35// VA_LIST can not initialize to NULL for all compiler, so we use this to\r
36// indicate a null VA_LIST\r
37//\r
38VA_LIST mVaListNull;\r
39\r
b29910d6
MM
40/**\r
41 Send message to DebugPort Protocol.\r
42\r
43 If mDebugPort is NULL, i.e. EFI_DEBUGPORT_PROTOCOL is not located,\r
44 EFI_DEBUGPORT_PROTOCOL is located first.\r
45 Then, Buffer is sent via EFI_DEBUGPORT_PROTOCOL.Write.\r
46\r
47 @param Buffer The message to be sent.\r
48 @param BufferLength The byte length of Buffer.\r
49**/\r
50VOID\r
51UefiDebugLibDebugPortProtocolWrite (\r
52 IN CONST CHAR8 *Buffer,\r
53 IN UINTN BufferLength\r
54 )\r
55{\r
56 UINTN Length;\r
57 EFI_STATUS Status;\r
58\r
59 //\r
60 // If mDebugPort is NULL, initialize first.\r
61 //\r
62 if (mDebugPort == NULL) {\r
63 Status = gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&mDebugPort);\r
64 if (EFI_ERROR (Status)) {\r
65 return;\r
66 }\r
67\r
68 mDebugPort->Reset (mDebugPort);\r
69 }\r
70\r
71 //\r
72 // EFI_DEBUGPORT_PROTOCOL.Write is called until all message is sent.\r
73 //\r
74 while (BufferLength > 0) {\r
75 Length = BufferLength;\r
76\r
77 Status = mDebugPort->Write (mDebugPort, WRITE_TIMEOUT, &Length, (VOID *) Buffer);\r
78 if (EFI_ERROR (Status) || BufferLength < Length) {\r
79 break;\r
80 }\r
81\r
82 Buffer += Length;\r
83 BufferLength -= Length;\r
84 }\r
85}\r
86\r
87/**\r
88 Prints a debug message to the debug output device if the specified error level is enabled.\r
89\r
9095d37b
LG
90 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function\r
91 GetDebugPrintErrorLevel (), then print the message specified by Format and the\r
b29910d6
MM
92 associated variable argument list to the debug output device.\r
93\r
94 If Format is NULL, then ASSERT().\r
95\r
96 @param ErrorLevel The error level of the debug message.\r
97 @param Format Format string for the debug message to print.\r
9095d37b 98 @param ... A variable argument list whose contents are accessed\r
b29910d6
MM
99 based on the format string specified by Format.\r
100\r
101**/\r
102VOID\r
103EFIAPI\r
104DebugPrint (\r
105 IN UINTN ErrorLevel,\r
106 IN CONST CHAR8 *Format,\r
107 ...\r
108 )\r
27d86bc1
BB
109{\r
110 VA_LIST Marker;\r
111\r
112 VA_START (Marker, Format);\r
113 DebugVPrint (ErrorLevel, Format, Marker);\r
114 VA_END (Marker);\r
115}\r
116\r
117\r
118/**\r
119 Prints a debug message to the debug output device if the specified\r
120 error level is enabled base on Null-terminated format string and a\r
121 VA_LIST argument list or a BASE_LIST argument list.\r
122\r
123 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function\r
124 GetDebugPrintErrorLevel (), then print the message specified by Format and\r
125 the associated variable argument list to the debug output device.\r
126\r
127 If Format is NULL, then ASSERT().\r
128\r
129 @param ErrorLevel The error level of the debug message.\r
130 @param Format Format string for the debug message to print.\r
131 @param VaListMarker VA_LIST marker for the variable argument list.\r
132 @param BaseListMarker BASE_LIST marker for the variable argument list.\r
133\r
134**/\r
135VOID\r
136DebugPrintMarker (\r
137 IN UINTN ErrorLevel,\r
138 IN CONST CHAR8 *Format,\r
139 IN VA_LIST VaListMarker,\r
140 IN BASE_LIST BaseListMarker\r
141 )\r
b29910d6
MM
142{\r
143 CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];\r
b29910d6
MM
144\r
145 //\r
146 // If Format is NULL, then ASSERT().\r
147 //\r
148 ASSERT (Format != NULL);\r
149\r
150 //\r
151 // Check driver debug mask value and global mask\r
152 //\r
153 if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {\r
154 return;\r
155 }\r
156\r
157 //\r
158 // Convert the DEBUG() message to an ASCII String\r
159 //\r
27d86bc1
BB
160 if (BaseListMarker == NULL) {\r
161 AsciiVSPrint (Buffer, sizeof (Buffer), Format, VaListMarker);\r
162 } else {\r
163 AsciiBSPrint (Buffer, sizeof (Buffer), Format, BaseListMarker);\r
164 }\r
b29910d6
MM
165\r
166 //\r
167 // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.\r
168 //\r
169 UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));\r
170}\r
171\r
172\r
27d86bc1
BB
173/**\r
174 Prints a debug message to the debug output device if the specified\r
175 error level is enabled.\r
176\r
177 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function\r
178 GetDebugPrintErrorLevel (), then print the message specified by Format and\r
179 the associated variable argument list to the debug output device.\r
180\r
181 If Format is NULL, then ASSERT().\r
182\r
183 @param ErrorLevel The error level of the debug message.\r
184 @param Format Format string for the debug message to print.\r
185 @param VaListMarker VA_LIST marker for the variable argument list.\r
186\r
187**/\r
188VOID\r
189EFIAPI\r
190DebugVPrint (\r
191 IN UINTN ErrorLevel,\r
192 IN CONST CHAR8 *Format,\r
193 IN VA_LIST VaListMarker\r
194 )\r
195{\r
196 DebugPrintMarker (ErrorLevel, Format, VaListMarker, NULL);\r
197}\r
198\r
199\r
200/**\r
201 Prints a debug message to the debug output device if the specified\r
202 error level is enabled.\r
203 This function use BASE_LIST which would provide a more compatible\r
204 service than VA_LIST.\r
205\r
206 If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function\r
207 GetDebugPrintErrorLevel (), then print the message specified by Format and\r
208 the associated variable argument list to the debug output device.\r
209\r
210 If Format is NULL, then ASSERT().\r
211\r
212 @param ErrorLevel The error level of the debug message.\r
213 @param Format Format string for the debug message to print.\r
214 @param BaseListMarker BASE_LIST marker for the variable argument list.\r
215\r
216**/\r
217VOID\r
218EFIAPI\r
219DebugBPrint (\r
220 IN UINTN ErrorLevel,\r
221 IN CONST CHAR8 *Format,\r
222 IN BASE_LIST BaseListMarker\r
223 )\r
224{\r
225 DebugPrintMarker (ErrorLevel, Format, mVaListNull, BaseListMarker);\r
226}\r
227\r
228\r
b29910d6 229/**\r
9095d37b 230 Prints an assert message containing a filename, line number, and description.\r
b29910d6
MM
231 This may be followed by a breakpoint or a dead loop.\r
232\r
233 Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"\r
9095d37b
LG
234 to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of\r
235 PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if\r
236 DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then\r
237 CpuDeadLoop() is called. If neither of these bits are set, then this function\r
b29910d6
MM
238 returns immediately after the message is printed to the debug output device.\r
239 DebugAssert() must actively prevent recursion. If DebugAssert() is called while\r
240 processing another DebugAssert(), then DebugAssert() must return immediately.\r
241\r
242 If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.\r
243 If Description is NULL, then a <Description> string of "(NULL) Description" is printed.\r
244\r
9095d37b 245 @param FileName The pointer to the name of the source file that generated\r
b29910d6 246 the assert condition.\r
9095d37b 247 @param LineNumber The line number in the source file that generated the\r
b29910d6
MM
248 assert condition\r
249 @param Description The pointer to the description of the assert condition.\r
250\r
251**/\r
252VOID\r
253EFIAPI\r
254DebugAssert (\r
255 IN CONST CHAR8 *FileName,\r
256 IN UINTN LineNumber,\r
257 IN CONST CHAR8 *Description\r
258 )\r
259{\r
260 CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];\r
261\r
262 //\r
263 // Generate the ASSERT() message in ASCII format\r
264 //\r
265 AsciiSPrint (\r
9095d37b
LG
266 Buffer,\r
267 sizeof (Buffer),\r
aa0a5149
BA
268 "ASSERT [%a] %a(%d): %a\n",\r
269 gEfiCallerBaseName,\r
9095d37b
LG
270 FileName,\r
271 LineNumber,\r
b29910d6
MM
272 Description\r
273 );\r
274\r
275 //\r
276 // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.\r
277 //\r
278 UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));\r
279\r
280 //\r
281 // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings\r
282 //\r
283 if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {\r
284 CpuBreakpoint ();\r
285 } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {\r
286 CpuDeadLoop ();\r
287 }\r
288}\r
289\r
290\r
291/**\r
292 Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.\r
293\r
9095d37b 294 This function fills Length bytes of Buffer with the value specified by\r
b29910d6
MM
295 PcdDebugClearMemoryValue, and returns Buffer.\r
296\r
297 If Buffer is NULL, then ASSERT().\r
9095d37b 298 If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().\r
b29910d6
MM
299\r
300 @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.\r
9095d37b 301 @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.\r
b29910d6
MM
302\r
303 @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue.\r
304\r
305**/\r
306VOID *\r
307EFIAPI\r
308DebugClearMemory (\r
309 OUT VOID *Buffer,\r
310 IN UINTN Length\r
311 )\r
312{\r
313 //\r
314 // If Buffer is NULL, then ASSERT().\r
315 //\r
316 ASSERT (Buffer != NULL);\r
317\r
318 //\r
319 // SetMem() checks for the the ASSERT() condition on Length and returns Buffer\r
320 //\r
321 return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue));\r
322}\r
323\r
324\r
325/**\r
326 Returns TRUE if ASSERT() macros are enabled.\r
327\r
9095d37b 328 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of\r
b29910d6
MM
329 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
330\r
331 @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.\r
332 @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.\r
333\r
334**/\r
335BOOLEAN\r
336EFIAPI\r
337DebugAssertEnabled (\r
338 VOID\r
339 )\r
340{\r
341 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);\r
342}\r
343\r
344\r
9095d37b 345/**\r
b29910d6
MM
346 Returns TRUE if DEBUG() macros are enabled.\r
347\r
9095d37b 348 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of\r
b29910d6
MM
349 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
350\r
351 @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.\r
352 @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.\r
353\r
354**/\r
355BOOLEAN\r
356EFIAPI\r
357DebugPrintEnabled (\r
358 VOID\r
359 )\r
360{\r
361 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);\r
362}\r
363\r
364\r
9095d37b 365/**\r
b29910d6
MM
366 Returns TRUE if DEBUG_CODE() macros are enabled.\r
367\r
9095d37b 368 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of\r
b29910d6
MM
369 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
370\r
371 @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.\r
372 @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.\r
373\r
374**/\r
375BOOLEAN\r
376EFIAPI\r
377DebugCodeEnabled (\r
378 VOID\r
379 )\r
380{\r
381 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);\r
382}\r
383\r
384\r
9095d37b 385/**\r
b29910d6
MM
386 Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.\r
387\r
9095d37b 388 This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of\r
b29910d6
MM
389 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
390\r
391 @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.\r
392 @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.\r
393\r
394**/\r
395BOOLEAN\r
396EFIAPI\r
397DebugClearMemoryEnabled (\r
398 VOID\r
399 )\r
400{\r
401 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);\r
402}\r
403\r
404/**\r
405 Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.\r
406\r
407 This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.\r
408\r
409 @retval TRUE Current ErrorLevel is supported.\r
410 @retval FALSE Current ErrorLevel is not supported.\r
411\r
412**/\r
413BOOLEAN\r
414EFIAPI\r
415DebugPrintLevelEnabled (\r
416 IN CONST UINTN ErrorLevel\r
417 )\r
418{\r
419 return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);\r
420}\r
50e7d3d9 421\r