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