73bb08e3574d67e9cc862b46318927ddbd389101
[mirror_edk2.git] / IntelFsp2Pkg / Library / BaseFspDebugLibSerialPort / DebugLib.c
1 /** @file\r
2 \r
3   Copyright (c) 2014 - 2015, 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   Get stack frame pointer of function call.\r
33 \r
34   @return StackFramePointer  stack frame pointer of function call.\r
35 **/\r
36 UINT32 *\r
37 EFIAPI\r
38 GetStackFramePointer (\r
39   VOID\r
40   );\r
41 \r
42 \r
43 /**\r
44   Prints a debug message to the debug output device if the specified error level is enabled.\r
45 \r
46   If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function\r
47   GetDebugPrintErrorLevel (), then print the message specified by Format and the\r
48   associated variable argument list to the debug output device.\r
49 \r
50   If Format is NULL, then ASSERT().\r
51 \r
52   @param  ErrorLevel  The error level of the debug message.\r
53   @param  Format      Format string for the debug message to print.\r
54   @param  ...         Variable argument list whose contents are accessed\r
55                       based on the format string specified by Format.\r
56 \r
57 **/\r
58 VOID\r
59 EFIAPI\r
60 DebugPrint (\r
61   IN  UINTN        ErrorLevel,\r
62   IN  CONST CHAR8  *Format,\r
63   ...\r
64   )\r
65 {\r
66   CHAR8    Buffer[MAX_DEBUG_MESSAGE_LENGTH];\r
67   VA_LIST  Marker;\r
68 \r
69   //\r
70   // If Format is NULL, then ASSERT().\r
71   //\r
72   if (!GetDebugPrintDeviceEnable ()) {\r
73     return;\r
74   }\r
75 \r
76   //\r
77   // Check driver debug mask value and global mask\r
78   //\r
79   if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {\r
80     return;\r
81   }\r
82 \r
83   //\r
84   // If Format is NULL, then ASSERT().\r
85   //\r
86   ASSERT (Format != NULL);\r
87 \r
88   //\r
89   // Convert the DEBUG() message to an ASCII String\r
90   //\r
91   VA_START (Marker, Format);\r
92   AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);\r
93   VA_END (Marker);\r
94 \r
95   //\r
96   // Send the print string to a Serial Port\r
97   //\r
98   SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));\r
99 }\r
100 \r
101 /**\r
102   Convert an UINT32 value into HEX string sepcified by Buffer.\r
103 \r
104   @param  Value   The HEX value to convert to string\r
105   @param  Buffer  The pointer to the target buffer to be filled with HEX string\r
106 \r
107 **/\r
108 VOID\r
109 FillHex (\r
110   UINT32   Value,\r
111   CHAR8   *Buffer\r
112   )\r
113 {\r
114   INTN  Idx;\r
115   for (Idx = 7; Idx >= 0; Idx--) {\r
116     Buffer[Idx] = mHexTable[Value & 0x0F];\r
117     Value >>= 4;\r
118   }\r
119 }\r
120 \r
121 /**\r
122   Prints an assert message containing a filename, line number, and description.\r
123   This may be followed by a breakpoint or a dead loop.\r
124 \r
125   Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"\r
126   to the debug output device.  If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of\r
127   PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if\r
128   DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then\r
129   CpuDeadLoop() is called.  If neither of these bits are set, then this function\r
130   returns immediately after the message is printed to the debug output device.\r
131   DebugAssert() must actively prevent recursion.  If DebugAssert() is called while\r
132   processing another DebugAssert(), then DebugAssert() must return immediately.\r
133 \r
134   If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.\r
135   If Description is NULL, then a <Description> string of "(NULL) Description" is printed.\r
136 \r
137 **/\r
138 VOID\r
139 DebugAssertInternal (\r
140   VOID\r
141   )\r
142 {\r
143   CHAR8     Buffer[MAX_DEBUG_MESSAGE_LENGTH];\r
144   UINT32   *Frame;\r
145 \r
146   Frame = (UINT32 *)GetStackFramePointer ();\r
147 \r
148   //\r
149   // Generate the ASSERT() message in Ascii format\r
150   //\r
151   AsciiStrnCpyS (\r
152     Buffer,\r
153     sizeof(Buffer) / sizeof(CHAR8),\r
154     "-> EBP:0x00000000  EIP:0x00000000\n",\r
155     sizeof(Buffer) / sizeof(CHAR8) - 1\r
156     );\r
157   SerialPortWrite ((UINT8 *)"ASSERT DUMP:\n", 13);\r
158   while (Frame != NULL) {\r
159     FillHex ((UINT32)Frame, Buffer + 9);\r
160     FillHex (Frame[1], Buffer + 9 + 8 + 8);\r
161     SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer));\r
162     if ((Frame[0] > (UINT32)Frame) && (Frame[0] < (UINT32)Frame + 0x00100000)) {\r
163       Frame = (UINT32 *)Frame[0];\r
164     } else {\r
165       Frame = NULL;\r
166     }\r
167   }\r
168 \r
169   //\r
170   // Dead loop\r
171   //\r
172   CpuDeadLoop ();\r
173 }\r
174 \r
175 /**\r
176   Prints an assert message containing a filename, line number, and description.\r
177   This may be followed by a breakpoint or a dead loop.\r
178 \r
179   Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"\r
180   to the debug output device.  If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of\r
181   PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if\r
182   DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then\r
183   CpuDeadLoop() is called.  If neither of these bits are set, then this function\r
184   returns immediately after the message is printed to the debug output device.\r
185   DebugAssert() must actively prevent recursion.  If DebugAssert() is called while\r
186   processing another DebugAssert(), then DebugAssert() must return immediately.\r
187 \r
188   If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.\r
189   If Description is NULL, then a <Description> string of "(NULL) Description" is printed.\r
190 \r
191   @param  FileName     The pointer to the name of the source file that generated the assert condition.\r
192   @param  LineNumber   The line number in the source file that generated the assert condition\r
193   @param  Description  The pointer to the description of the assert condition.\r
194 \r
195 **/\r
196 VOID\r
197 EFIAPI\r
198 DebugAssert (\r
199   IN CONST CHAR8  *FileName,\r
200   IN UINTN        LineNumber,\r
201   IN CONST CHAR8  *Description\r
202   )\r
203 {\r
204   DebugAssertInternal ();\r
205 }\r
206 \r
207 \r
208 /**\r
209   Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.\r
210 \r
211   This function fills Length bytes of Buffer with the value specified by\r
212   PcdDebugClearMemoryValue, and returns Buffer.\r
213 \r
214   If Buffer is NULL, then ASSERT().\r
215   If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().\r
216 \r
217   @param   Buffer  The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.\r
218   @param   Length  The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.\r
219 \r
220   @return  Buffer  The pointer to the target buffer filled with PcdDebugClearMemoryValue.\r
221 \r
222 **/\r
223 VOID *\r
224 EFIAPI\r
225 DebugClearMemory (\r
226   OUT VOID  *Buffer,\r
227   IN UINTN  Length\r
228   )\r
229 {\r
230   return Buffer;\r
231 }\r
232 \r
233 \r
234 /**\r
235   Returns TRUE if ASSERT() macros are enabled.\r
236 \r
237   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of\r
238   PcdDebugProperyMask is set.  Otherwise FALSE is returned.\r
239 \r
240   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.\r
241   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.\r
242 \r
243 **/\r
244 BOOLEAN\r
245 EFIAPI\r
246 DebugAssertEnabled (\r
247   VOID\r
248   )\r
249 {\r
250   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);\r
251 }\r
252 \r
253 \r
254 /**\r
255   Returns TRUE if DEBUG() macros are enabled.\r
256 \r
257   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of\r
258   PcdDebugProperyMask is set.  Otherwise FALSE is returned.\r
259 \r
260   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.\r
261   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.\r
262 \r
263 **/\r
264 BOOLEAN\r
265 EFIAPI\r
266 DebugPrintEnabled (\r
267   VOID\r
268   )\r
269 {\r
270   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);\r
271 }\r
272 \r
273 /**\r
274   Returns TRUE if DEBUG_CODE() macros are enabled.\r
275 \r
276   This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of\r
277   PcdDebugProperyMask is set.  Otherwise FALSE is returned.\r
278 \r
279   @retval  TRUE    The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.\r
280   @retval  FALSE   The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.\r
281 \r
282 **/\r
283 BOOLEAN\r
284 EFIAPI\r
285 DebugCodeEnabled (\r
286   VOID\r
287   )\r
288 {\r
289   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);\r
290 }\r
291 \r
292 \r
293 /**\r
294   Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.\r
295 \r
296   This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of\r
297   PcdDebugProperyMask is set.  Otherwise FALSE is returned.\r
298 \r
299   @retval  TRUE    The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.\r
300   @retval  FALSE   The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.\r
301 \r
302 **/\r
303 BOOLEAN\r
304 EFIAPI\r
305 DebugClearMemoryEnabled (\r
306   VOID\r
307   )\r
308 {\r
309   return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);\r
310 }\r
311 \r
312 /**\r
313   Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.\r
314 \r
315   This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.\r
316 \r
317   @retval  TRUE    Current ErrorLevel is supported.\r
318   @retval  FALSE   Current ErrorLevel is not supported.\r
319 \r
320 **/\r
321 BOOLEAN\r
322 EFIAPI\r
323 DebugPrintLevelEnabled (\r
324   IN  CONST UINTN        ErrorLevel\r
325   )\r
326 {\r
327   return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);\r
328 }\r