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