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 - 2011, Intel Corporation. All rights reserved.<BR>
11   This program and the accompanying materials
12   are licensed and made available under the terms and conditions of the BSD License
13   which accompanies this distribution.  The full text of the license may be found at
14   http://opensource.org/licenses/bsd-license.php.
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 
19 **/
20 
21 #include <Base.h>
22 #include <Library/DebugLib.h>
23 #include <Library/BaseLib.h>
24 #include <Library/PrintLib.h>
25 #include <Library/PcdLib.h>
26 #include <Library/BaseMemoryLib.h>
27 #include <Library/SerialPortLib.h>
28 #include <Library/DebugPrintErrorLevelLib.h>
29 
30 //
31 // Define the maximum debug and assert message length that this library supports
32 //
33 #define MAX_DEBUG_MESSAGE_LENGTH  0x100
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   CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];
74   VA_LIST  Marker;
75 
76   //
77   // If Format is NULL, then ASSERT().
78   //
79   ASSERT (Format != NULL);
80 
81   //
82   // Check driver debug mask value and global mask
83   //
84   if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
85     return;
86   }
87 
88   //
89   // Convert the DEBUG() message to an ASCII String
90   //
91   VA_START (Marker, Format);
92   AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
93   VA_END (Marker);
94 
95   //
96   // Send the print string to a Serial Port
97   //
98   SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
99 }
100 
101 
102 /**
103   Prints an assert message containing a filename, line number, and description.
104   This may be followed by a breakpoint or a dead loop.
105 
106   Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
107   to the debug output device.  If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
108   PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
109   DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
110   CpuDeadLoop() is called.  If neither of these bits are set, then this function
111   returns immediately after the message is printed to the debug output device.
112   DebugAssert() must actively prevent recursion.  If DebugAssert() is called while
113   processing another DebugAssert(), then DebugAssert() must return immediately.
114 
115   If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
116   If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
117 
118   @param  FileName     The pointer to the name of the source file that generated the assert condition.
119   @param  LineNumber   The line number in the source file that generated the assert condition
120   @param  Description  The pointer to the description of the assert condition.
121 
122 **/
123 VOID
124 EFIAPI
DebugAssert(IN CONST CHAR8 * FileName,IN UINTN LineNumber,IN CONST CHAR8 * Description)125 DebugAssert (
126   IN CONST CHAR8  *FileName,
127   IN UINTN        LineNumber,
128   IN CONST CHAR8  *Description
129   )
130 {
131   CHAR8  Buffer[MAX_DEBUG_MESSAGE_LENGTH];
132 
133   //
134   // Generate the ASSERT() message in Ascii format
135   //
136   AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT [%a] %a(%d): %a\n", gEfiCallerBaseName, FileName, LineNumber, Description);
137 
138   //
139   // Send the print string to the Console Output device
140   //
141   SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));
142 
143   //
144   // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
145   //
146   if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
147     CpuBreakpoint ();
148   } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
149     CpuDeadLoop ();
150   }
151 }
152 
153 
154 /**
155   Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
156 
157   This function fills Length bytes of Buffer with the value specified by
158   PcdDebugClearMemoryValue, and returns Buffer.
159 
160   If Buffer is NULL, then ASSERT().
161   If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
162 
163   @param   Buffer  The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
164   @param   Length  The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
165 
166   @return  Buffer  The pointer to the target buffer filled with PcdDebugClearMemoryValue.
167 
168 **/
169 VOID *
170 EFIAPI
DebugClearMemory(OUT VOID * Buffer,IN UINTN Length)171 DebugClearMemory (
172   OUT VOID  *Buffer,
173   IN UINTN  Length
174   )
175 {
176   //
177   // If Buffer is NULL, then ASSERT().
178   //
179   ASSERT (Buffer != NULL);
180 
181   //
182   // SetMem() checks for the the ASSERT() condition on Length and returns Buffer
183   //
184   return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue));
185 }
186 
187 
188 /**
189   Returns TRUE if ASSERT() macros are enabled.
190 
191   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
192   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
193 
194   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
195   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
196 
197 **/
198 BOOLEAN
199 EFIAPI
DebugAssertEnabled(VOID)200 DebugAssertEnabled (
201   VOID
202   )
203 {
204   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
205 }
206 
207 
208 /**
209   Returns TRUE if DEBUG() macros are enabled.
210 
211   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
212   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
213 
214   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
215   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
216 
217 **/
218 BOOLEAN
219 EFIAPI
DebugPrintEnabled(VOID)220 DebugPrintEnabled (
221   VOID
222   )
223 {
224   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
225 }
226 
227 
228 /**
229   Returns TRUE if DEBUG_CODE() macros are enabled.
230 
231   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
232   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
233 
234   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
235   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
236 
237 **/
238 BOOLEAN
239 EFIAPI
DebugCodeEnabled(VOID)240 DebugCodeEnabled (
241   VOID
242   )
243 {
244   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
245 }
246 
247 
248 /**
249   Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
250 
251   This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
252   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
253 
254   @retval  TRUE    The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
255   @retval  FALSE   The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
256 
257 **/
258 BOOLEAN
259 EFIAPI
DebugClearMemoryEnabled(VOID)260 DebugClearMemoryEnabled (
261   VOID
262   )
263 {
264   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
265 }
266 
267 /**
268   Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.
269 
270   This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.
271 
272   @retval  TRUE    Current ErrorLevel is supported.
273   @retval  FALSE   Current ErrorLevel is not supported.
274 
275 **/
276 BOOLEAN
277 EFIAPI
DebugPrintLevelEnabled(IN CONST UINTN ErrorLevel)278 DebugPrintLevelEnabled (
279   IN  CONST UINTN        ErrorLevel
280   )
281 {
282   return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);
283 }
284 
285