]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/DebugLib.c
Correct parameter names for ASSERT() checks.
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / PeiDxeDebugLibReportStatusCode / DebugLib.c
CommitLineData
2287f237 1/** @file\r
2 Debug Library that fowards all messages to ReportStatusCode()\r
3\r
4 Copyright (c) 2006, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15\r
16\r
17#include <FrameworkPei.h>\r
551ed06f 18#include <FrameworkModuleBase.h>\r
2287f237 19#include <Guid/StatusCodeDataTypeId.h>\r
20\r
21#include <Library/DebugLib.h>\r
22#include <Library/BaseLib.h>\r
23#include <Library/BaseMemoryLib.h>\r
24#include <Library/ReportStatusCodeLib.h>\r
25#include <Library/PcdLib.h>\r
26\r
27#include <DebugInfo.h>\r
28\r
29/**\r
30\r
31 Prints a debug message to the debug output device if the specified error level is enabled.\r
32\r
33 If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print\r
34 the message specified by Format and the associated variable argument list to\r
35 the debug output device.\r
36\r
37 If Format is NULL, then ASSERT().\r
38\r
39 @param ErrorLevel The error level of the debug message.\r
40 @param Format Format string for the debug message to print.\r
967c09fa 41 @param ... Variable argument list whose contents are accessed \r
42 based on the format string specified by Format.\r
2287f237 43\r
44**/\r
45VOID\r
46EFIAPI\r
47DebugPrint (\r
48 IN UINTN ErrorLevel,\r
49 IN CONST CHAR8 *Format,\r
50 ...\r
51 )\r
52{\r
53 UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof (UINT64)];\r
54 EFI_DEBUG_INFO *DebugInfo;\r
55 UINTN TotalSize;\r
ca9938b8 56 VA_LIST VaListMarker;\r
57 BASE_LIST BaseListMarker;\r
58 CHAR8 *FormatString;\r
59 BOOLEAN Long;\r
60 BOOLEAN Done;\r
2287f237 61\r
62 //\r
63 // If Format is NULL, then ASSERT().\r
64 //\r
65 ASSERT (Format != NULL);\r
66\r
67 //\r
68 // Check driver Debug Level value and global debug level\r
69 //\r
70 if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) {\r
71 return;\r
72 }\r
73\r
ca9938b8 74 //\r
75 // Compute the total size of the record\r
76 //\r
2287f237 77 TotalSize = sizeof (EFI_DEBUG_INFO) + 12 * sizeof (UINT64) + AsciiStrLen (Format) + 1;\r
ca9938b8 78\r
79 //\r
80 // If the TotalSize is larger than the maximum record size, then ASSERT()\r
81 //\r
82 ASSERT (TotalSize <= EFI_STATUS_CODE_DATA_MAX_SIZE);\r
83\r
84 //\r
85 // If the TotalSize is larger than the maximum record size, then return\r
86 //\r
2287f237 87 if (TotalSize > EFI_STATUS_CODE_DATA_MAX_SIZE) {\r
88 return;\r
89 }\r
90\r
91 //\r
ca9938b8 92 // Fill in EFI_DEBUG_INFO\r
2287f237 93 //\r
ca9938b8 94 DebugInfo = (EFI_DEBUG_INFO *)Buffer;\r
2287f237 95 DebugInfo->ErrorLevel = (UINT32)ErrorLevel;\r
ca9938b8 96 BaseListMarker = (BASE_LIST)(DebugInfo + 1);\r
97 FormatString = (UINT8 *)((UINT64 *)(DebugInfo + 1) + 12);\r
98\r
99 //\r
100 // Copy the Format string into the record\r
101 //\r
102 AsciiStrCpy (FormatString, Format);\r
2287f237 103\r
104 //\r
105 // 256 byte mini Var Arg stack. That is followed by the format string.\r
106 //\r
ca9938b8 107 VA_START (VaListMarker, Format);\r
108 for (; *Format != '\0'; Format++) {\r
109 if (*Format != '%') {\r
110 continue;\r
111 }\r
112 Long = FALSE;\r
113 //\r
114 // Parse Flags and Width\r
115 //\r
116 for (Done = FALSE; !Done; ) {\r
117 Format++;\r
118 switch (*Format) {\r
119 case '.': \r
120 case '-': \r
121 case '+': \r
122 case ' ': \r
123 case ',': \r
124 case '0':\r
125 case '1':\r
126 case '2':\r
127 case '3':\r
128 case '4':\r
129 case '5':\r
130 case '6':\r
131 case '7':\r
132 case '8':\r
133 case '9':\r
134 break;\r
135 case 'L':\r
136 case 'l': \r
137 Long = TRUE;\r
138 break;\r
139 case '*':\r
140 BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);\r
141 break;\r
142 case '\0':\r
143 //\r
144 // Make no output if Format string terminates unexpectedly when\r
145 // looking up for flag, width, precision and type. \r
146 //\r
147 Format--;\r
148 //\r
149 // break skipped on purpose.\r
150 //\r
151 default:\r
152 Done = TRUE;\r
153 break;\r
154 }\r
155 } \r
156 \r
157 //\r
158 // Handle each argument type\r
159 //\r
160 switch (*Format) {\r
161 case 'p':\r
162 if (sizeof (VOID *) > 4) {\r
163 Long = TRUE;\r
164 }\r
165 case 'X':\r
166 case 'x':\r
167 case 'd':\r
168 if (Long) {\r
169 BASE_ARG (BaseListMarker, INT64) = VA_ARG (VaListMarker, INT64);\r
170 } else {\r
171 BASE_ARG (BaseListMarker, int) = VA_ARG (VaListMarker, int);\r
172 }\r
173 break;\r
174 case 's':\r
175 case 'S':\r
176 case 'a':\r
177 case 'g':\r
178 case 't':\r
179 BASE_ARG (BaseListMarker, VOID *) = VA_ARG (VaListMarker, VOID *);\r
180 break;\r
181 case 'c':\r
182 BASE_ARG (BaseListMarker, UINTN) = VA_ARG (VaListMarker, UINTN);\r
183 break;\r
184 case 'r':\r
185 BASE_ARG (BaseListMarker, RETURN_STATUS) = VA_ARG (VaListMarker, RETURN_STATUS);\r
186 break;\r
187 }\r
188\r
189 //\r
190 // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then ASSERT()\r
191 // This indicates that the DEBUG() macro is passing in more argument than can be handled by \r
192 // the EFI_DEBUG_INFO record\r
193 //\r
194 ASSERT ((UINT8 *)BaseListMarker <= FormatString);\r
195\r
196 //\r
197 // If the converted BASE_LIST is larger than the 12 * sizeof (UINT64) allocated bytes, then return\r
198 //\r
199 if ((UINT8 *)BaseListMarker > FormatString) {\r
200 return;\r
201 }\r
2287f237 202 }\r
ca9938b8 203 VA_END (VaListMarker);\r
2287f237 204\r
ca9938b8 205 //\r
206 // Send the DebugInfo record\r
207 //\r
2287f237 208 REPORT_STATUS_CODE_EX (\r
209 EFI_DEBUG_CODE,\r
210 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED),\r
211 0,\r
212 NULL,\r
213 &gEfiStatusCodeDataTypeDebugGuid,\r
214 DebugInfo,\r
215 TotalSize\r
216 );\r
217}\r
218\r
2287f237 219/**\r
220\r
221 Prints an assert message containing a filename, line number, and description.\r
222 This may be followed by a breakpoint or a dead loop.\r
223\r
224 Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"\r
225 to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of\r
226 PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if\r
227 DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then\r
228 CpuDeadLoop() is called. If neither of these bits are set, then this function\r
229 returns immediately after the message is printed to the debug output device.\r
584125bc 230 DebugAssert() must actively prevent recursion. If DebugAssert() is called while\r
2287f237 231 processing another DebugAssert(), then DebugAssert() must return immediately.\r
232\r
233 If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.\r
234\r
235 If Description is NULL, then a <Description> string of "(NULL) Description" is printed.\r
236\r
237 @param FileName Pointer to the name of the source file that generated the assert condition.\r
238 @param LineNumber The line number in the source file that generated the assert condition\r
239 @param Description Pointer to the description of the assert condition.\r
240\r
241**/\r
242VOID\r
243EFIAPI\r
244DebugAssert (\r
245 IN CONST CHAR8 *FileName,\r
246 IN UINTN LineNumber,\r
247 IN CONST CHAR8 *Description\r
248 )\r
249{\r
250 UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof(UINT64)];\r
251 EFI_DEBUG_ASSERT_DATA *AssertData;\r
252 UINTN TotalSize;\r
253 CHAR8 *Temp;\r
254 UINTN FileNameLength;\r
255 UINTN DescriptionLength;\r
256\r
257 //\r
258 // Make sure it will all fit in the passed in buffer\r
259 //\r
260 FileNameLength = AsciiStrLen (FileName);\r
261 DescriptionLength = AsciiStrLen (Description);\r
262 TotalSize = sizeof (EFI_DEBUG_ASSERT_DATA) + FileNameLength + 1 + DescriptionLength + 1;\r
263 if (TotalSize <= EFI_STATUS_CODE_DATA_MAX_SIZE) {\r
264 //\r
265 // Fill in EFI_DEBUG_ASSERT_DATA\r
266 //\r
267 AssertData = (EFI_DEBUG_ASSERT_DATA *)Buffer;\r
268 AssertData->LineNumber = (UINT32)LineNumber;\r
269\r
270 //\r
271 // Copy Ascii FileName including NULL.\r
272 //\r
273 Temp = AsciiStrCpy ((CHAR8 *)(AssertData + 1), FileName);\r
274\r
275 //\r
276 // Copy Ascii Description\r
277 //\r
278 AsciiStrCpy (Temp + AsciiStrLen (FileName) + 1, Description);\r
279\r
8191cd5e 280 REPORT_STATUS_CODE_EX (\r
2287f237 281 (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),\r
282 (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE),\r
8191cd5e
LG
283 0,\r
284 NULL,\r
285 &gEfiStatusCodeDataTypeAssertGuid,\r
2287f237 286 AssertData,\r
287 TotalSize\r
288 );\r
289 }\r
290\r
291 //\r
292 // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings\r
293 //\r
294 if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {\r
295 CpuBreakpoint ();\r
296 } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {\r
297 CpuDeadLoop ();\r
298 }\r
299}\r
300\r
301\r
302/**\r
303\r
304 Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.\r
305\r
306 This function fills Length bytes of Buffer with the value specified by\r
307 PcdDebugClearMemoryValue, and returns Buffer.\r
308\r
309 If Buffer is NULL, then ASSERT().\r
310\r
311 If Length is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT().\r
312\r
313 @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue.\r
314 @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.\r
315\r
316 @return Buffer\r
317\r
318**/\r
319VOID *\r
320EFIAPI\r
321DebugClearMemory (\r
322 OUT VOID *Buffer,\r
323 IN UINTN Length\r
324 )\r
325{\r
326 //\r
327 // If Buffer is NULL, then ASSERT().\r
328 //\r
329 ASSERT (Buffer != NULL);\r
330\r
331 //\r
332 // SetMem() checks for the the ASSERT() condition on Length and returns Buffer\r
333 //\r
334 return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue));\r
335}\r
336\r
337\r
338/**\r
339\r
340 Returns TRUE if ASSERT() macros are enabled.\r
341\r
342 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of\r
343 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
344\r
345 @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.\r
346 @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.\r
347\r
348**/\r
349BOOLEAN\r
350EFIAPI\r
351DebugAssertEnabled (\r
352 VOID\r
353 )\r
354{\r
355 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);\r
356}\r
357\r
358\r
359/**\r
360\r
361 Returns TRUE if DEBUG()macros are enabled.\r
362\r
363 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of\r
364 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
365\r
366 @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.\r
367 @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.\r
368\r
369**/\r
370BOOLEAN\r
371EFIAPI\r
372DebugPrintEnabled (\r
373 VOID\r
374 )\r
375{\r
376 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);\r
377}\r
378\r
379\r
380/**\r
381\r
382 Returns TRUE if DEBUG_CODE()macros are enabled.\r
383\r
384 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of\r
385 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
386\r
387 @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.\r
388 @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.\r
389\r
390**/\r
391BOOLEAN\r
392EFIAPI\r
393DebugCodeEnabled (\r
394 VOID\r
395 )\r
396{\r
397 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);\r
398}\r
399\r
400\r
401/**\r
402\r
403 Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled.\r
404\r
405 This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of\r
406 PcdDebugProperyMask is set. Otherwise FALSE is returned.\r
407\r
408 @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.\r
409 @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.\r
410\r
411**/\r
412BOOLEAN\r
413EFIAPI\r
414DebugClearMemoryEnabled (\r
415 VOID\r
416 )\r
417{\r
418 return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);\r
419}\r