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