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