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