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