• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   UEFI Debug Library that sends messages to EFI_DEBUGPORT_PROTOCOL.Write.
3 
4   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php.
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <Uefi.h>
16 
17 #include <Library/DebugLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/PrintLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/BaseLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugPrintErrorLevelLib.h>
24 
25 #include <Protocol/DebugPort.h>
26 
27 //
28 // Define the maximum debug and assert message length that this library supports
29 //
30 #define MAX_DEBUG_MESSAGE_LENGTH  0x100
31 
32 //
33 // Define the timeout for EFI_DEBUGPORT_PROTOCOL.Write
34 //
35 #define WRITE_TIMEOUT 1000
36 
37 
38 EFI_DEBUGPORT_PROTOCOL *mDebugPort = NULL;
39 
40 /**
41   Send message to DebugPort Protocol.
42 
43   If mDebugPort is NULL, i.e. EFI_DEBUGPORT_PROTOCOL is not located,
44   EFI_DEBUGPORT_PROTOCOL is located first.
45   Then, Buffer is sent via EFI_DEBUGPORT_PROTOCOL.Write.
46 
47   @param  Buffer         The message to be sent.
48   @param  BufferLength   The byte length of Buffer.
49 **/
50 VOID
UefiDebugLibDebugPortProtocolWrite(IN CONST CHAR8 * Buffer,IN UINTN BufferLength)51 UefiDebugLibDebugPortProtocolWrite (
52   IN  CONST CHAR8  *Buffer,
53   IN        UINTN  BufferLength
54   )
55 {
56   UINTN      Length;
57   EFI_STATUS Status;
58 
59   //
60   // If mDebugPort is NULL, initialize first.
61   //
62   if (mDebugPort == NULL) {
63       Status = gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&mDebugPort);
64       if (EFI_ERROR (Status)) {
65           return;
66       }
67 
68       mDebugPort->Reset (mDebugPort);
69   }
70 
71   //
72   // EFI_DEBUGPORT_PROTOCOL.Write is called until all message is sent.
73   //
74   while (BufferLength > 0) {
75     Length = BufferLength;
76 
77     Status = mDebugPort->Write (mDebugPort, WRITE_TIMEOUT, &Length, (VOID *) Buffer);
78     if (EFI_ERROR (Status) || BufferLength < Length) {
79       break;
80     }
81 
82     Buffer += Length;
83     BufferLength -= Length;
84   }
85 }
86 
87 /**
88   Prints a debug message to the debug output device if the specified error level is enabled.
89 
90   If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
91   GetDebugPrintErrorLevel (), then print the message specified by Format and the
92   associated variable argument list to the debug output device.
93 
94   If Format is NULL, then ASSERT().
95 
96   @param  ErrorLevel  The error level of the debug message.
97   @param  Format      Format string for the debug message to print.
98   @param  ...         A variable argument list whose contents are accessed
99                       based on the format string specified by Format.
100 
101 **/
102 VOID
103 EFIAPI
DebugPrint(IN UINTN ErrorLevel,IN CONST CHAR8 * Format,...)104 DebugPrint (
105   IN  UINTN        ErrorLevel,
106   IN  CONST CHAR8  *Format,
107   ...
108   )
109 {
110   CHAR8      Buffer[MAX_DEBUG_MESSAGE_LENGTH];
111   VA_LIST    Marker;
112 
113   //
114   // If Format is NULL, then ASSERT().
115   //
116   ASSERT (Format != NULL);
117 
118   //
119   // Check driver debug mask value and global mask
120   //
121   if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
122     return;
123   }
124 
125   //
126   // Convert the DEBUG() message to an ASCII String
127   //
128   VA_START (Marker, Format);
129   AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
130   VA_END (Marker);
131 
132   //
133   // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.
134   //
135   UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));
136 }
137 
138 
139 /**
140   Prints an assert message containing a filename, line number, and description.
141   This may be followed by a breakpoint or a dead loop.
142 
143   Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
144   to the debug output device.  If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
145   PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
146   DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
147   CpuDeadLoop() is called.  If neither of these bits are set, then this function
148   returns immediately after the message is printed to the debug output device.
149   DebugAssert() must actively prevent recursion.  If DebugAssert() is called while
150   processing another DebugAssert(), then DebugAssert() must return immediately.
151 
152   If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
153   If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
154 
155   @param  FileName     The pointer to the name of the source file that generated
156                        the assert condition.
157   @param  LineNumber   The line number in the source file that generated the
158                        assert condition
159   @param  Description  The pointer to the description of the assert condition.
160 
161 **/
162 VOID
163 EFIAPI
DebugAssert(IN CONST CHAR8 * FileName,IN UINTN LineNumber,IN CONST CHAR8 * Description)164 DebugAssert (
165   IN CONST CHAR8  *FileName,
166   IN UINTN        LineNumber,
167   IN CONST CHAR8  *Description
168   )
169 {
170   CHAR8  Buffer[MAX_DEBUG_MESSAGE_LENGTH];
171 
172   //
173   // Generate the ASSERT() message in ASCII format
174   //
175   AsciiSPrint (
176     Buffer,
177     sizeof (Buffer),
178     "ASSERT [%a] %a(%d): %a\n",
179     gEfiCallerBaseName,
180     FileName,
181     LineNumber,
182     Description
183     );
184 
185   //
186   // Send the print string to EFI_DEBUGPORT_PROTOCOL.Write.
187   //
188   UefiDebugLibDebugPortProtocolWrite (Buffer, AsciiStrLen (Buffer));
189 
190   //
191   // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
192   //
193   if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
194     CpuBreakpoint ();
195   } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
196     CpuDeadLoop ();
197   }
198 }
199 
200 
201 /**
202   Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
203 
204   This function fills Length bytes of Buffer with the value specified by
205   PcdDebugClearMemoryValue, and returns Buffer.
206 
207   If Buffer is NULL, then ASSERT().
208   If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
209 
210   @param   Buffer  The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
211   @param   Length  The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
212 
213   @return  Buffer  The pointer to the target buffer filled with PcdDebugClearMemoryValue.
214 
215 **/
216 VOID *
217 EFIAPI
DebugClearMemory(OUT VOID * Buffer,IN UINTN Length)218 DebugClearMemory (
219   OUT VOID  *Buffer,
220   IN UINTN  Length
221   )
222 {
223   //
224   // If Buffer is NULL, then ASSERT().
225   //
226   ASSERT (Buffer != NULL);
227 
228   //
229   // SetMem() checks for the the ASSERT() condition on Length and returns Buffer
230   //
231   return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue));
232 }
233 
234 
235 /**
236   Returns TRUE if ASSERT() macros are enabled.
237 
238   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
239   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
240 
241   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
242   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
243 
244 **/
245 BOOLEAN
246 EFIAPI
DebugAssertEnabled(VOID)247 DebugAssertEnabled (
248   VOID
249   )
250 {
251   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
252 }
253 
254 
255 /**
256   Returns TRUE if DEBUG() macros are enabled.
257 
258   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
259   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
260 
261   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
262   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
263 
264 **/
265 BOOLEAN
266 EFIAPI
DebugPrintEnabled(VOID)267 DebugPrintEnabled (
268   VOID
269   )
270 {
271   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
272 }
273 
274 
275 /**
276   Returns TRUE if DEBUG_CODE() macros are enabled.
277 
278   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
279   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
280 
281   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
282   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
283 
284 **/
285 BOOLEAN
286 EFIAPI
DebugCodeEnabled(VOID)287 DebugCodeEnabled (
288   VOID
289   )
290 {
291   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
292 }
293 
294 
295 /**
296   Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
297 
298   This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
299   PcdDebugProperyMask is set.  Otherwise FALSE is returned.
300 
301   @retval  TRUE    The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
302   @retval  FALSE   The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
303 
304 **/
305 BOOLEAN
306 EFIAPI
DebugClearMemoryEnabled(VOID)307 DebugClearMemoryEnabled (
308   VOID
309   )
310 {
311   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
312 }
313 
314 /**
315   Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.
316 
317   This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.
318 
319   @retval  TRUE    Current ErrorLevel is supported.
320   @retval  FALSE   Current ErrorLevel is not supported.
321 
322 **/
323 BOOLEAN
324 EFIAPI
DebugPrintLevelEnabled(IN CONST UINTN ErrorLevel)325 DebugPrintLevelEnabled (
326   IN  CONST UINTN        ErrorLevel
327   )
328 {
329   return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);
330 }
331 
332