blob: 5c3e312158a1cc271fdcb5bd23439801c60c30bf [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/**
2 * @file
3 *
4 * AMD Integrated Debug Print Routines
5 *
6 * Contains all functions related to IDS Debug Print
7 *
8 * @xrefitem bom "File Content Label" "Release Content"
9 * @e project: AGESA
10 * @e sub-project: IDS
11 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
12 */
13/*****************************************************************************
Siyuan Wang641f00c2013-06-08 11:50:55 +080014 * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
15 * All rights reserved.
zbao7d94cf92012-07-02 14:19:14 +080016 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080017 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are met:
19 * * Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * * Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
zbao7d94cf92012-07-02 14:19:14 +080027 *
Siyuan Wang641f00c2013-06-08 11:50:55 +080028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
zbao7d94cf92012-07-02 14:19:14 +080038 ******************************************************************************
39 */
40
41 /*----------------------------------------------------------------------------------------
42 * M O D U L E S U S E D
43 *----------------------------------------------------------------------------------------
44 */
45#include "AGESA.h"
46#include "Ids.h"
47#include "IdsLib.h"
48#include "amdlib.h"
49#include "IdsDebugPrint.h"
50#include "Filecode.h"
51CODE_GROUP (G1_PEICC)
52RDATA_GROUP (G1_PEICC)
53
54#define FILECODE PROC_IDS_DEBUG_IDSDEBUGPRINT_FILECODE
55
56//
57// Also support coding convention rules for var arg macros
58//
59#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
60typedef CHAR8 *VA_LIST;
61#define VA_START(ap, v) (ap = (VA_LIST) & (v) + _INT_SIZE_OF (v))
62#define VA_ARG(ap, t) (*(t *) ((ap += _INT_SIZE_OF (t)) - _INT_SIZE_OF (t)))
63#define VA_END(ap) (ap = (VA_LIST) 0)
64
65#define LEFT_JUSTIFY 0x01
66#define PREFIX_SIGN 0x02
67#define PREFIX_BLANK 0x04
68#define COMMA_TYPE 0x08
69#define LONG_TYPE 0x10
70#define PREFIX_ZERO 0x20
71
72#define MAX_LOCAL_BUFFER_SIZE 512
73#define BUFFER_OVERFLOW 0xFFFF
74
75/**
76 * Check If any print service is enabled.
77 *
78 * @param[in] DebugPrintList The Pointer to print service list
79 *
80 * @retval TRUE At least on print service is enabled
81 * @retval FALSE All print service is disabled
82 *
83 **/
84STATIC BOOLEAN
85AmdIdsDebugPrintCheckSupportAll (
86 IN IDS_DEBUG_PRINT **DebugPrintList
87 )
88{
89 BOOLEAN IsSupported;
90 UINTN i;
91 IsSupported = FALSE;
92 for (i = 0; DebugPrintList[i] != NULL; i++) {
93 if (DebugPrintList[i]->support ()) {
94 IsSupported = TRUE;
95 }
96 }
97 return IsSupported;
98}
99
100/**
101 * Parses flag and width information from theFormat string and returns the next index
102 * into the Format string that needs to be parsed. See file headed for details of Flag and Width.
103 *
104 * @param[in] Format Current location in the AvSPrint format string.
105 * @param[out] Flags Returns flags
106 * @param[out] Width Returns width of element
107 * @param[out] Marker Vararg list that may be partially consumed and returned.
108 *
109 * @retval Pointer indexed into the Format string for all the information parsed by this routine.
110 *
111 **/
112STATIC CHAR8 *
113GetFlagsAndWidth (
114 IN CHAR8 *Format,
115 OUT UINTN *Flags,
116 OUT UINTN *Width,
117 IN OUT VA_LIST *Marker
118 )
119{
120 UINTN Count;
121 BOOLEAN Done;
122
123 *Flags = 0;
124 *Width = 0;
125 for (Done = FALSE; !Done; ) {
126 Format++;
127
128 switch (*Format) {
129
130 case '-': /* ' - ' */
131 *Flags |= LEFT_JUSTIFY;
132 break;
133 case '+': /* ' + ' */
134 *Flags |= PREFIX_SIGN;
135 break;
136 case ' ':
137 *Flags |= PREFIX_BLANK;
138 break;
139 case ',': /* ', ' */
140 *Flags |= COMMA_TYPE;
141 break;
142 case 'L':
143 case 'l':
144 *Flags |= LONG_TYPE;
145 break;
146
147 case '*':
148 *Width = VA_ARG (*Marker, UINTN);
149 break;
150
151 case '0':
152 *Flags |= PREFIX_ZERO;
153 break;
154
155 case '1':
156 case '2':
157 case '3':
158 case '4':
159 case '5':
160 case '6':
161 case '7':
162 case '8':
163 case '9':
164 Count = 0;
165 do {
166 Count = (Count * 10) + *Format - '0';
167 Format++;
168 } while ((*Format >= '0') && (*Format <= '9'));
169 Format--;
170 *Width = Count;
171 break;
172
173 default:
174 Done = TRUE;
175 }
176 }
177 return Format;
178}
179
180CHAR8 STATIC HexStr[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
181extern CONST IDS_DEBUG_PRINT* ROMDATA IdsDebugPrint[];
182
183/**
184 *
185 * @param[in,out] Value - Hex value to convert to a string in Buffer.
186 *
187 *
188 */
189VOID
190GetDebugPrintList (
191 IN OUT CONST IDS_DEBUG_PRINT ***pIdsDebugPrintListPtr
192 )
193{
194 *pIdsDebugPrintListPtr = &IdsDebugPrint[0];
195}
196
197/**
198 *
199 * @param[in,out] Buffer Location to place ascii hex string of Value.
200 * @param[in] Value - Hex value to convert to a string in Buffer.
201 * @param[in] Flags - Flags to use in printing Hex string, see file header for details.
202 * @param[in] Width - Width of hex value.
203 * @param[in,out] BufferSize - Size of input buffer
204 *
205 * @retval Number of characters printed.
206 **/
207
208STATIC UINTN
209ValueToHexStr (
210 IN OUT CHAR8 *Buffer,
211 IN UINT64 Value,
212 IN UINTN Flags,
213 IN UINTN Width,
214 IN OUT UINTN *BufferSize
215 )
216{
217 CHAR8 TempBuffer[30];
218 CHAR8 *TempStr;
219 CHAR8 Prefix;
220 CHAR8 *BufferPtr;
221 UINTN Count;
222 UINTN Index;
223
224 TempStr = TempBuffer;
225 BufferPtr = Buffer;
226 //
227 // Count starts at one since we will null terminate. Each iteration of the
228 // loop picks off one nibble. Oh yea TempStr ends up backwards
229 //
230 Count = 0;
231 do {
232 *(TempStr++) = HexStr[Value & 0x0f];
233 Value >>= 4;
234 Count++;
235 } while (Value != 0);
236
237 if (Flags & PREFIX_ZERO) {
238 Prefix = '0';
239 } else if (!(Flags & LEFT_JUSTIFY)) {
240 Prefix = ' ';
241 } else {
242 Prefix = 0x00;
243 }
244 for (Index = Count; Index < Width; Index++) {
245 *(TempStr++) = Prefix;
246 }
247
248 //
249 // Reverse temp string into Buffer.
250 //
251 while (TempStr != TempBuffer) {
252 (*BufferSize)--;
253 if (*BufferSize == 0) {
254 return BUFFER_OVERFLOW;
255 }
256 *(BufferPtr++) = *(--TempStr);
257 }
258
259 *BufferPtr = 0;
260 return Index;
261}
262
263/**
264 * Prints a Value as a decimal number in Buffer
265 *
266 * @param[in] Buffer Location to place ascii decimal number string of Value.
267 * @param[in] Value Decimal value to convert to a string in Buffer.
268 * @param[in] Flags Flags to use in printing decimal string, see file header for details.
269 * @param[in,out] BufferSize Size of input buffer
270 *
271 * @retval Number of characters printed.
272 *
273**/
274
275STATIC UINTN
276ValueToString (
277 IN OUT CHAR8 *Buffer,
278 IN INT32 Value,
279 IN UINTN Flags,
280 IN OUT UINTN *BufferSize
281 )
282{
283 CHAR8 TempBuffer[30];
284 CHAR8 *TempStr;
285 CHAR8 *BufferPtr;
286 UINTN Count;
287 UINTN Remainder;
288
289 ASSERT (*BufferSize);
290 TempStr = TempBuffer;
291 BufferPtr = Buffer;
292 Count = 0;
293
294 if (Value < 0) {
295 (*BufferSize)--;
296 if (*BufferSize == 0) {
297 return BUFFER_OVERFLOW;
298 }
299 *(BufferPtr++) = '-'; /* ' - ' */
300 Value = - Value;
301 Count++;
302 }
303
304 do {
305 Remainder = Value % 10;
306 Value /= 10;
307 *(TempStr++) = (CHAR8)(Remainder + '0');
308 Count++;
309 if ((Flags & COMMA_TYPE) == COMMA_TYPE) {
310 if (Count % 3 == 0) {
311 *(TempStr++) = ',';
312 }
313 }
314 } while (Value != 0);
315
316 //
317 // Reverse temp string into Buffer.
318 //
319 while (TempStr != TempBuffer) {
320 (*BufferSize)--;
321 if (*BufferSize == 0) {
322 return BUFFER_OVERFLOW;
323 }
324 *(BufferPtr++) = *(--TempStr);
325 }
326
327 *BufferPtr = 0;
328 return Count;
329}
330
331/**
332 * Worker function for print string to buffer
333 *
334 * @param[in] Flag - filter flag
335 * @param[in] *Format - format string
336 * @param[in] Marker - Variable parameter
337 * @param[in] Buffer - Point to input buffer
338 * @param[in] BufferSize - Buffer size
339 * @param[out] OutputStringLen - output string length, include '\0' at the end
340 *
341 * @retval IDS_DEBUG_PRINT_SUCCESS succeed
342 * @retval IDS_DEBUG_PRINT_BUFFER_OVERFLOW input buffer overflow
343**/
344STATIC IDS_DEBUG_PRINT_STATUS
345AmdIdsDebugPrintWorker (
346 IN CONST CHAR8 *Format,
347 IN VA_LIST Marker,
348 IN CHAR8 *Buffer,
349 IN UINTN BufferSize,
350 OUT UINTN *OutputStringLen
351 )
352{
353 UINTN Index;
354 UINTN Length;
355 UINTN Flags;
356 UINTN Width;
357 UINT64 Value;
358 CHAR8 *AsciiStr;
359
360 //Init the default Value
361 Index = 0;
362 //
363 // Process format string
364 //
365 for (; (*Format != '\0') && (BufferSize > 0); Format++) {
366 if (*Format != '%') {
367 Buffer[Index++] = *Format;
368 BufferSize--;
369 } else {
370 Format = GetFlagsAndWidth ((CHAR8 *)Format, &Flags, &Width, &Marker);
371 switch (*Format) {
372 case 'X':
373 Flags |= PREFIX_ZERO;
374 Width = sizeof (UINT64) * 2;
Jacob Garber4c33a3a2019-07-12 10:34:06 -0600375 // fall through
zbao7d94cf92012-07-02 14:19:14 +0800376 case 'x':
377 if ((Flags & LONG_TYPE) == LONG_TYPE) {
378 Value = VA_ARG (Marker, UINT64);
379 } else {
380 Value = VA_ARG (Marker, UINTN);
381 }
382 Length = ValueToHexStr (&Buffer[Index], Value, Flags, Width, &BufferSize);
383 if (Length != BUFFER_OVERFLOW) {
384 Index += Length;
385 } else {
386 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
387 }
388 break;
389
390 case 'd':
391 Value = (UINTN)VA_ARG (Marker, UINT32);
392 Length = ValueToString (&Buffer[Index], (UINT32)Value, Flags, &BufferSize);
393 if (Length != BUFFER_OVERFLOW) {
394 Index += Length;
395 } else {
396 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
397 }
398
399 break;
400
401 case 's':
402 case 'S':
403 AsciiStr = (CHAR8 *)VA_ARG (Marker, CHAR8 *);
404 while (*AsciiStr != '\0') {
405 BufferSize--;
406 if (BufferSize == 0) {
407 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
408 }
409 Buffer[Index++] = *AsciiStr++;
410 }
411 break;
412
413 case 'c':
414 BufferSize--;
415 if (BufferSize == 0) {
416 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
417 }
418 Buffer[Index++] = (CHAR8)VA_ARG (Marker, UINTN);
419 break;
420
421 case 'v':
422 ASSERT (FALSE); // %v is no longer supported
423 break;
424
425 case '%':
426 BufferSize--;
427 if (BufferSize == 0) {
428 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
429 }
430 Buffer[Index++] = *Format;
431 break;
432
433 default:
434 //
435 // if the type is unknown print it to the screen
436 //
437 BufferSize--;
438 if (BufferSize == 0) {
439 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
440 }
441 Buffer[Index++] = '%';
442
443 BufferSize--;
444 if (BufferSize == 0) {
445 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
446 }
447 Buffer[Index++] = *Format;
448 break;
449 }
450 }
451 }
452 if (BufferSize == 0) {
453 return IDS_DEBUG_PRINT_BUFFER_OVERFLOW;
454 }
455 //Mark the end of word
456 Buffer[Index] = 0;
457 *OutputStringLen = Index;
458 return IDS_DEBUG_PRINT_SUCCESS;
459}
460
461
462/**
463 * Insert Overflow warning to the tail of output
464 *
465 * @param[in] Buffer - Point to input buffer
466 * @param[in] BufferSize - Buffer size
467 *
468**/
469STATIC VOID
470InsertOverflowWarningMessage (
471 IN CHAR8 *Buffer,
472 IN UINTN BufferSize
473 )
474{
475 CHAR8 *Destination;
476 CHAR8 WarningString[] = "\n#BUFFER OVERFLOW#\n";
477 AMD_CONFIG_PARAMS StdHeader;
478
479 Destination = Buffer + BufferSize - sizeof (WarningString);
480 LibAmdMemCopy (Destination, WarningString, sizeof (WarningString), &StdHeader);
481}
482
483/**
484 * Process debug string
485 *
486 * @param[in] Flag - filter flag
487 * @param[in] *Format - format string
488 * @param[in] Marker - Variable parameter
489 *
490**/
491STATIC VOID
492AmdIdsDebugPrintProcess (
493 IN UINT64 Flag,
494 IN CONST CHAR8 *Format,
495 IN VA_LIST Marker
496 )
497{
498 UINT64 Filter;
499 CHAR8 LocalBuffer[MAX_LOCAL_BUFFER_SIZE];
500 UINTN OutPutStringLen;
501 IDS_DEBUG_PRINT **DebugPrintList;
502 IDS_DEBUG_PRINT_PRIVATE_DATA debugPrintPrivate;
503 UINT8 i;
504
505
506 GetDebugPrintList ((CONST IDS_DEBUG_PRINT ***)&DebugPrintList);
507 if (AmdIdsDebugPrintCheckSupportAll (DebugPrintList)) {
508 if (AmdIdsDebugPrintWorker (Format, Marker, &LocalBuffer[0], sizeof (LocalBuffer), &OutPutStringLen) == IDS_DEBUG_PRINT_BUFFER_OVERFLOW) {
509 InsertOverflowWarningMessage (&LocalBuffer[0], sizeof (LocalBuffer));
510 OutPutStringLen = sizeof (LocalBuffer);
511 }
512
513 //init input
514 debugPrintPrivate.saveContext = FALSE;
515
516 for (i = 0; DebugPrintList[i] != NULL; i++) {
517 if (DebugPrintList[i]->support ()) {
518 Filter = IDS_DEBUG_PRINT_MASK;
519 //Get Customize filter (Option)
520 DebugPrintList[i]->customfilter (&Filter);
521 if (Flag & Filter) {
522 //Init Private Date (Option)
523 DebugPrintList[i]->InitPrivateData (Flag, &debugPrintPrivate);
524 //Print Physical Layer
525 DebugPrintList[i]->print (&LocalBuffer[0], OutPutStringLen, &debugPrintPrivate);
526 }
527 }
528 }
529 }
530}
531
532/**
533 * Prints string to debug host like printf in C
534 *
535 * @param[in] Flag - filter flag
536 * @param[in] *Format - format string
537 * @param[in] ... Variable parameter
538 *
539**/
540VOID
541AmdIdsDebugPrint (
542 IN UINT64 Flag,
543 IN CONST CHAR8 *Format,
544 IN ...
545 )
546{
547 VA_LIST Marker;
548 VA_START (Marker, Format); //init marker to 1st dynamic parameters.
549 AmdIdsDebugPrintProcess (Flag, Format, Marker);
550 VA_END (Marker);
551}
552
553/**
554 * Prints memory debug strings
555 *
556 * @param[in] *Format - format string
557 * @param[in] ... Variable parameter
558 *
559**/
560VOID
561AmdIdsDebugPrintMem (
562 IN CHAR8 *Format,
563 IN ...
564 )
565{
566 VA_LIST Marker;
567 VA_START (Marker, Format); //init marker to 1st dynamic parameters.
568 AmdIdsDebugPrintProcess (MEM_FLOW, Format, Marker);
569 VA_END (Marker);
570}
571
572/**
573 * Prints CPU debug strings
574 *
575 * @param[in] *Format - format string
576 * @param[in] ... Variable parameter
577 *
578**/
579VOID
580AmdIdsDebugPrintCpu (
581 IN CHAR8 *Format,
582 IN ...
583 )
584{
585 VA_LIST Marker;
586 VA_START (Marker, Format); //init marker to 1st dynamic parameters.
587 AmdIdsDebugPrintProcess (CPU_TRACE, Format, Marker);
588 VA_END (Marker);
589}
590
591
592/**
593 * Prints HT debug strings
594 *
595 * @param[in] *Format - format string
596 * @param[in] ... Variable parameter
597 *
598**/
599VOID
600AmdIdsDebugPrintHt (
601 IN CHAR8 *Format,
602 IN ...
603 )
604{
605 VA_LIST Marker;
606 VA_START (Marker, Format); //init marker to 1st dynamic parameters.
607 AmdIdsDebugPrintProcess (HT_TRACE, Format, Marker);
608 VA_END (Marker);
609}
610
611
612/**
613 * Prints GNB debug strings
614 *
615 * @param[in] *Format - format string
616 * @param[in] ... Variable parameter
617 *
618**/
619VOID
620AmdIdsDebugPrintGnb (
621 IN CHAR8 *Format,
622 IN ...
623 )
624{
625 VA_LIST Marker;
626 VA_START (Marker, Format); //init marker to 1st dynamic parameters.
627 AmdIdsDebugPrintProcess (GNB_TRACE, Format, Marker);
628 VA_END (Marker);
629}
630
631/**
632 * Prints debug strings in any condition
633 *
634 * @param[in] *Format - format string
635 * @param[in] ... Variable parameter
636 *
637**/
638VOID
639AmdIdsDebugPrintAll (
640 IN CHAR8 *Format,
641 IN ...
642 )
643{
644 VA_LIST Marker;
645 VA_START (Marker, Format); //init marker to 1st dynamic parameters.
646 AmdIdsDebugPrintProcess (TRACE_MASK_ALL, Format, Marker);
647 VA_END (Marker);
648}
649