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