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