• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*++
2 
3 Copyright (c) 1998  Intel Corporation
4 
5 Module Name:
6 
7     print.c
8 
9 Abstract:
10 
11 
12 
13 
14 Revision History
15 
16 --*/
17 
18 #include "lib.h"
19 #include "efistdarg.h"                        // !!!
20 
21 //
22 // Declare runtime functions
23 //
24 
25 #ifdef RUNTIME_CODE
26 #ifndef __GNUC__
27 #pragma RUNTIME_CODE(DbgPrint)
28 
29 // For debugging..
30 
31 /*
32 #pragma RUNTIME_CODE(_Print)
33 #pragma RUNTIME_CODE(PFLUSH)
34 #pragma RUNTIME_CODE(PSETATTR)
35 #pragma RUNTIME_CODE(PPUTC)
36 #pragma RUNTIME_CODE(PGETC)
37 #pragma RUNTIME_CODE(PITEM)
38 #pragma RUNTIME_CODE(ValueToHex)
39 #pragma RUNTIME_CODE(ValueToString)
40 #pragma RUNTIME_CODE(TimeToString)
41 */
42 
43 #endif /* !defined(__GNUC__) */
44 #endif
45 
46 //
47 //
48 //
49 
50 
51 #define PRINT_STRING_LEN            200
52 #define PRINT_ITEM_BUFFER_LEN       100
53 
54 typedef struct {
55     BOOLEAN             Ascii;
56     UINTN               Index;
57     union {
58         CHAR16          *pw;
59         CHAR8           *pc;
60     } un;
61 } POINTER;
62 
63 #define pw	un.pw
64 #define pc	un.pc
65 
66 typedef struct _pitem {
67 
68     POINTER     Item;
69     CHAR16      Scratch[PRINT_ITEM_BUFFER_LEN];
70     UINTN       Width;
71     UINTN       FieldWidth;
72     UINTN       *WidthParse;
73     CHAR16      Pad;
74     BOOLEAN     PadBefore;
75     BOOLEAN     Comma;
76     BOOLEAN     Long;
77 } PRINT_ITEM;
78 
79 
80 typedef struct _pstate {
81     // Input
82     POINTER     fmt;
83     va_list     args;
84 
85     // Output
86     CHAR16      *Buffer;
87     CHAR16      *End;
88     CHAR16      *Pos;
89     UINTN       Len;
90 
91     UINTN       Attr;
92     UINTN       RestoreAttr;
93 
94     UINTN       AttrNorm;
95     UINTN       AttrHighlight;
96     UINTN       AttrError;
97 
98     INTN EFIAPI       (*Output)(VOID *context, CHAR16 *str);
99     INTN EFIAPI       (*SetAttr)(VOID *context, UINTN attr);
100     VOID        *Context;
101 
102     // Current item being formatted
103     struct _pitem  *Item;
104 } PRINT_STATE;
105 
106 //
107 // Internal fucntions
108 //
109 
110 STATIC
111 UINTN
112 _Print (
113     IN PRINT_STATE     *ps
114     );
115 
116 STATIC
117 UINTN
118 _IPrint (
119     IN UINTN                            Column,
120     IN UINTN                            Row,
121     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
122     IN CHAR16                           *fmt,
123     IN CHAR8                            *fmta,
124     IN va_list                          args
125     );
126 
127 STATIC
128 INTN EFIAPI
129 _DbgOut (
130     IN VOID     *Context,
131     IN CHAR16   *Buffer
132     );
133 
134 STATIC
135 VOID
136 PFLUSH (
137     IN OUT PRINT_STATE     *ps
138     );
139 
140 STATIC
141 VOID
142 PPUTC (
143     IN OUT PRINT_STATE     *ps,
144     IN CHAR16              c
145     );
146 
147 STATIC
148 VOID
149 PITEM (
150     IN OUT PRINT_STATE  *ps
151     );
152 
153 STATIC
154 CHAR16
155 PGETC (
156     IN POINTER      *p
157     );
158 
159 STATIC
160 VOID
161 PSETATTR (
162     IN OUT PRINT_STATE  *ps,
163     IN UINTN             Attr
164     );
165 
166 //
167 //
168 //
169 
170 INTN EFIAPI
171 _SPrint (
172     IN VOID     *Context,
173     IN CHAR16   *Buffer
174     );
175 
176 INTN EFIAPI
177 _PoolPrint (
178     IN VOID     *Context,
179     IN CHAR16   *Buffer
180     );
181 
182 INTN
DbgPrint(IN INTN mask,IN CHAR8 * fmt,...)183 DbgPrint (
184     IN INTN      mask,
185     IN CHAR8     *fmt,
186     ...
187     )
188 /*++
189 
190 Routine Description:
191 
192     Prints a formatted unicode string to the default StandardError console
193 
194 Arguments:
195 
196     mask        - Bit mask of debug string.  If a bit is set in the
197                   mask that is also set in EFIDebug the string is
198                   printed; otherwise, the string is not printed
199 
200     fmt         - Format string
201 
202 Returns:
203 
204     Length of string printed to the StandardError console
205 
206 --*/
207 {
208     SIMPLE_TEXT_OUTPUT_INTERFACE    *DbgOut;
209     PRINT_STATE     ps;
210     va_list         args;
211     UINTN           back;
212     UINTN           attr;
213     UINTN           SavedAttribute;
214 
215 
216     if (!(EFIDebug & mask)) {
217         return 0;
218     }
219 
220     va_start (args, fmt);
221     ZeroMem (&ps, sizeof(ps));
222 
223     ps.Output = _DbgOut;
224     ps.fmt.Ascii = TRUE;
225     ps.fmt.pc = fmt;
226     va_copy(ps.args, args);
227     ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED);
228 
229     DbgOut = LibRuntimeDebugOut;
230 
231     if (!DbgOut) {
232         DbgOut = ST->StdErr;
233     }
234 
235     if (DbgOut) {
236         ps.Attr = DbgOut->Mode->Attribute;
237         ps.Context = DbgOut;
238         ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN))  DbgOut->SetAttribute;
239     }
240 
241     SavedAttribute = ps.Attr;
242 
243     back = (ps.Attr >> 4) & 0xf;
244     ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
245     ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
246     ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
247 
248     attr = ps.AttrNorm;
249 
250     if (mask & D_WARN) {
251         attr = ps.AttrHighlight;
252     }
253 
254     if (mask & D_ERROR) {
255         attr = ps.AttrError;
256     }
257 
258     if (ps.SetAttr) {
259         ps.Attr = attr;
260         ps.SetAttr (ps.Context, attr);
261     }
262 
263     _Print (&ps);
264 
265     va_end (ps.args);
266     va_end (args);
267 
268     //
269     // Restore original attributes
270     //
271 
272     if (ps.SetAttr) {
273         ps.SetAttr (ps.Context, SavedAttribute);
274     }
275 
276     return 0;
277 }
278 
279 STATIC
280 INTN
IsLocalPrint(void * func)281 IsLocalPrint(void *func)
282 {
283 	if (func == _DbgOut || func == _SPrint || func == _PoolPrint)
284 		return 1;
285 	return 0;
286 }
287 
288 STATIC
289 INTN EFIAPI
_DbgOut(IN VOID * Context,IN CHAR16 * Buffer)290 _DbgOut (
291     IN VOID     *Context,
292     IN CHAR16   *Buffer
293     )
294 // Append string worker for DbgPrint
295 {
296     SIMPLE_TEXT_OUTPUT_INTERFACE    *DbgOut;
297 
298     DbgOut = Context;
299 //    if (!DbgOut && ST && ST->ConOut) {
300 //        DbgOut = ST->ConOut;
301 //    }
302 
303     if (DbgOut) {
304 	if (IsLocalPrint(DbgOut->OutputString))
305 		DbgOut->OutputString(DbgOut, Buffer);
306         else
307 		uefi_call_wrapper(DbgOut->OutputString, 2, DbgOut, Buffer);
308     }
309 
310     return 0;
311 }
312 
313 INTN EFIAPI
_SPrint(IN VOID * Context,IN CHAR16 * Buffer)314 _SPrint (
315     IN VOID     *Context,
316     IN CHAR16   *Buffer
317     )
318 // Append string worker for SPrint, PoolPrint and CatPrint
319 {
320     UINTN           len;
321     POOL_PRINT      *spc;
322 
323     spc = Context;
324     len = StrLen(Buffer);
325 
326     //
327     // Is the string is over the max truncate it
328     //
329 
330     if (spc->len + len > spc->maxlen) {
331         len = spc->maxlen - spc->len;
332     }
333 
334     //
335     // Append the new text
336     //
337 
338     CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16));
339     spc->len += len;
340 
341     //
342     // Null terminate it
343     //
344 
345     if (spc->len < spc->maxlen) {
346         spc->str[spc->len] = 0;
347     } else if (spc->maxlen) {
348         spc->str[spc->maxlen-1] = 0;
349     }
350 
351     return 0;
352 }
353 
354 
355 INTN EFIAPI
_PoolPrint(IN VOID * Context,IN CHAR16 * Buffer)356 _PoolPrint (
357     IN VOID     *Context,
358     IN CHAR16   *Buffer
359     )
360 // Append string worker for PoolPrint and CatPrint
361 {
362     UINTN           newlen;
363     POOL_PRINT      *spc;
364 
365     spc = Context;
366     newlen = spc->len + StrLen(Buffer) + 1;
367 
368     //
369     // Is the string is over the max, grow the buffer
370     //
371 
372     if (newlen > spc->maxlen) {
373 
374         //
375         // Grow the pool buffer
376         //
377 
378         newlen += PRINT_STRING_LEN;
379         spc->maxlen = newlen;
380         spc->str = ReallocatePool (
381                         spc->str,
382                         spc->len * sizeof(CHAR16),
383                         spc->maxlen * sizeof(CHAR16)
384                         );
385 
386         if (!spc->str) {
387             spc->len = 0;
388             spc->maxlen = 0;
389         }
390     }
391 
392     //
393     // Append the new text
394     //
395 
396     return _SPrint (Context, Buffer);
397 }
398 
399 
400 
401 VOID
_PoolCatPrint(IN CHAR16 * fmt,IN va_list args,IN OUT POOL_PRINT * spc,IN INTN EFIAPI (* Output)(VOID * context,CHAR16 * str))402 _PoolCatPrint (
403     IN CHAR16           *fmt,
404     IN va_list          args,
405     IN OUT POOL_PRINT   *spc,
406     IN INTN EFIAPI      (*Output)(VOID *context, CHAR16 *str)
407     )
408 // Dispath function for SPrint, PoolPrint, and CatPrint
409 {
410     PRINT_STATE         ps;
411 
412     ZeroMem (&ps, sizeof(ps));
413     ps.Output  = Output;
414     ps.Context = spc;
415     ps.fmt.pw = fmt;
416     va_copy(ps.args, args);
417     _Print (&ps);
418     va_end(ps.args);
419 }
420 
421 
422 
423 UINTN
VSPrint(OUT CHAR16 * Str,IN UINTN StrSize,IN CHAR16 * fmt,va_list args)424 VSPrint (
425     OUT CHAR16  *Str,
426     IN UINTN    StrSize,
427     IN CHAR16   *fmt,
428     va_list     args
429     )
430 /*++
431 
432 Routine Description:
433 
434     Prints a formatted unicode string to a buffer using a va_list
435 
436 Arguments:
437 
438     Str         - Output buffer to print the formatted string into
439 
440     StrSize     - Size of Str.  String is truncated to this size.
441                   A size of 0 means there is no limit
442 
443     fmt         - The format string
444 
445     args        - va_list
446 
447 
448 Returns:
449 
450     String length returned in buffer
451 
452 --*/
453 {
454     POOL_PRINT          spc;
455 
456     spc.str    = Str;
457     spc.maxlen = StrSize / sizeof(CHAR16) - 1;
458     spc.len    = 0;
459 
460     _PoolCatPrint (fmt, args, &spc, _SPrint);
461 
462     return spc.len;
463 }
464 
465 UINTN
SPrint(OUT CHAR16 * Str,IN UINTN StrSize,IN CHAR16 * fmt,...)466 SPrint (
467     OUT CHAR16  *Str,
468     IN UINTN    StrSize,
469     IN CHAR16   *fmt,
470     ...
471     )
472 /*++
473 
474 Routine Description:
475 
476     Prints a formatted unicode string to a buffer
477 
478 Arguments:
479 
480     Str         - Output buffer to print the formatted string into
481 
482     StrSize     - Size of Str.  String is truncated to this size.
483                   A size of 0 means there is no limit
484 
485     fmt         - The format string
486 
487 Returns:
488 
489     String length returned in buffer
490 
491 --*/
492 {
493     va_list          args;
494     UINTN            len;
495 
496     va_start (args, fmt);
497     len = VSPrint(Str, StrSize, fmt, args);
498     va_end (args);
499 
500     return len;
501 }
502 
503 
504 CHAR16 *
PoolPrint(IN CHAR16 * fmt,...)505 PoolPrint (
506     IN CHAR16           *fmt,
507     ...
508     )
509 /*++
510 
511 Routine Description:
512 
513     Prints a formatted unicode string to allocated pool.  The caller
514     must free the resulting buffer.
515 
516 Arguments:
517 
518     fmt         - The format string
519 
520 Returns:
521 
522     Allocated buffer with the formatted string printed in it.
523     The caller must free the allocated buffer.   The buffer
524     allocation is not packed.
525 
526 --*/
527 {
528     POOL_PRINT          spc;
529     va_list             args;
530 
531     ZeroMem (&spc, sizeof(spc));
532     va_start (args, fmt);
533     _PoolCatPrint (fmt, args, &spc, _PoolPrint);
534     va_end (args);
535     return spc.str;
536 }
537 
538 
539 
540 CHAR16 *
CatPrint(IN OUT POOL_PRINT * Str,IN CHAR16 * fmt,...)541 CatPrint (
542     IN OUT POOL_PRINT   *Str,
543     IN CHAR16           *fmt,
544     ...
545     )
546 /*++
547 
548 Routine Description:
549 
550     Concatenates a formatted unicode string to allocated pool.
551     The caller must free the resulting buffer.
552 
553 Arguments:
554 
555     Str         - Tracks the allocated pool, size in use, and
556                   amount of pool allocated.
557 
558     fmt         - The format string
559 
560 Returns:
561 
562     Allocated buffer with the formatted string printed in it.
563     The caller must free the allocated buffer.   The buffer
564     allocation is not packed.
565 
566 --*/
567 {
568     va_list             args;
569 
570     va_start (args, fmt);
571     _PoolCatPrint (fmt, args, Str, _PoolPrint);
572     va_end (args);
573     return Str->str;
574 }
575 
576 
577 
578 UINTN
Print(IN CHAR16 * fmt,...)579 Print (
580     IN CHAR16   *fmt,
581     ...
582     )
583 /*++
584 
585 Routine Description:
586 
587     Prints a formatted unicode string to the default console
588 
589 Arguments:
590 
591     fmt         - Format string
592 
593 Returns:
594 
595     Length of string printed to the console
596 
597 --*/
598 {
599     va_list     args;
600     UINTN       back;
601 
602     va_start (args, fmt);
603     back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
604     va_end (args);
605     return back;
606 }
607 
608 UINTN
VPrint(IN CHAR16 * fmt,va_list args)609 VPrint (
610     IN CHAR16   *fmt,
611     va_list     args
612     )
613 /*++
614 
615 Routine Description:
616 
617     Prints a formatted unicode string to the default console using a va_list
618 
619 Arguments:
620 
621     fmt         - Format string
622     args        - va_list
623 Returns:
624 
625     Length of string printed to the console
626 
627 --*/
628 {
629     return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
630 }
631 
632 
633 UINTN
PrintAt(IN UINTN Column,IN UINTN Row,IN CHAR16 * fmt,...)634 PrintAt (
635     IN UINTN     Column,
636     IN UINTN     Row,
637     IN CHAR16    *fmt,
638     ...
639     )
640 /*++
641 
642 Routine Description:
643 
644     Prints a formatted unicode string to the default console, at
645     the supplied cursor position
646 
647 Arguments:
648 
649     Column, Row - The cursor position to print the string at
650 
651     fmt         - Format string
652 
653 Returns:
654 
655     Length of string printed to the console
656 
657 --*/
658 {
659     va_list     args;
660     UINTN       back;
661 
662     va_start (args, fmt);
663     back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
664     va_end (args);
665     return back;
666 }
667 
668 
669 UINTN
IPrint(IN SIMPLE_TEXT_OUTPUT_INTERFACE * Out,IN CHAR16 * fmt,...)670 IPrint (
671     IN SIMPLE_TEXT_OUTPUT_INTERFACE    *Out,
672     IN CHAR16                          *fmt,
673     ...
674     )
675 /*++
676 
677 Routine Description:
678 
679     Prints a formatted unicode string to the specified console
680 
681 Arguments:
682 
683     Out         - The console to print the string too
684 
685     fmt         - Format string
686 
687 Returns:
688 
689     Length of string printed to the console
690 
691 --*/
692 {
693     va_list     args;
694     UINTN       back;
695 
696     va_start (args, fmt);
697     back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
698     va_end (args);
699     return back;
700 }
701 
702 
703 UINTN
IPrintAt(IN SIMPLE_TEXT_OUTPUT_INTERFACE * Out,IN UINTN Column,IN UINTN Row,IN CHAR16 * fmt,...)704 IPrintAt (
705     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
706     IN UINTN                            Column,
707     IN UINTN                            Row,
708     IN CHAR16                           *fmt,
709     ...
710     )
711 /*++
712 
713 Routine Description:
714 
715     Prints a formatted unicode string to the specified console, at
716     the supplied cursor position
717 
718 Arguments:
719 
720     Out         - The console to print the string too
721 
722     Column, Row - The cursor position to print the string at
723 
724     fmt         - Format string
725 
726 Returns:
727 
728     Length of string printed to the console
729 
730 --*/
731 {
732     va_list     args;
733     UINTN       back;
734 
735     va_start (args, fmt);
736     back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
737     va_end (args);
738     return back;
739 }
740 
741 
742 UINTN
_IPrint(IN UINTN Column,IN UINTN Row,IN SIMPLE_TEXT_OUTPUT_INTERFACE * Out,IN CHAR16 * fmt,IN CHAR8 * fmta,IN va_list args)743 _IPrint (
744     IN UINTN                            Column,
745     IN UINTN                            Row,
746     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
747     IN CHAR16                           *fmt,
748     IN CHAR8                            *fmta,
749     IN va_list                          args
750     )
751 // Display string worker for: Print, PrintAt, IPrint, IPrintAt
752 {
753     PRINT_STATE     ps;
754     UINTN            back;
755 
756     ZeroMem (&ps, sizeof(ps));
757     ps.Context = Out;
758     ps.Output  = (INTN EFIAPI (*)(VOID *, CHAR16 *)) Out->OutputString;
759     ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN))  Out->SetAttribute;
760     ps.Attr = Out->Mode->Attribute;
761 
762     back = (ps.Attr >> 4) & 0xF;
763     ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
764     ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
765     ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
766 
767     if (fmt) {
768         ps.fmt.pw = fmt;
769     } else {
770         ps.fmt.Ascii = TRUE;
771         ps.fmt.pc = fmta;
772     }
773 
774     va_copy(ps.args, args);
775 
776     if (Column != (UINTN) -1) {
777         uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row);
778     }
779 
780     back = _Print (&ps);
781     va_end(ps.args);
782     return back;
783 }
784 
785 
786 UINTN
APrint(IN CHAR8 * fmt,...)787 APrint (
788     IN CHAR8    *fmt,
789     ...
790     )
791 /*++
792 
793 Routine Description:
794 
795     For those whom really can't deal with unicode, a print
796     function that takes an ascii format string
797 
798 Arguments:
799 
800     fmt         - ascii format string
801 
802 Returns:
803 
804     Length of string printed to the console
805 
806 --*/
807 
808 {
809     va_list     args;
810     UINTN       back;
811 
812     va_start (args, fmt);
813     back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
814     va_end (args);
815     return back;
816 }
817 
818 
819 STATIC
820 VOID
PFLUSH(IN OUT PRINT_STATE * ps)821 PFLUSH (
822     IN OUT PRINT_STATE     *ps
823     )
824 {
825     *ps->Pos = 0;
826     if (IsLocalPrint(ps->Output))
827 	ps->Output(ps->Context, ps->Buffer);
828     else
829     	uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
830     ps->Pos = ps->Buffer;
831 }
832 
833 STATIC
834 VOID
PSETATTR(IN OUT PRINT_STATE * ps,IN UINTN Attr)835 PSETATTR (
836     IN OUT PRINT_STATE  *ps,
837     IN UINTN             Attr
838     )
839 {
840    PFLUSH (ps);
841 
842    ps->RestoreAttr = ps->Attr;
843    if (ps->SetAttr) {
844 	uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
845    }
846 
847    ps->Attr = Attr;
848 }
849 
850 STATIC
851 VOID
PPUTC(IN OUT PRINT_STATE * ps,IN CHAR16 c)852 PPUTC (
853     IN OUT PRINT_STATE     *ps,
854     IN CHAR16              c
855     )
856 {
857     // if this is a newline, add a carraige return
858     if (c == '\n') {
859         PPUTC (ps, '\r');
860     }
861 
862     *ps->Pos = c;
863     ps->Pos += 1;
864     ps->Len += 1;
865 
866     // if at the end of the buffer, flush it
867     if (ps->Pos >= ps->End) {
868         PFLUSH(ps);
869     }
870 }
871 
872 
873 STATIC
874 CHAR16
PGETC(IN POINTER * p)875 PGETC (
876     IN POINTER      *p
877     )
878 {
879     CHAR16      c;
880 
881     c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
882     p->Index += 1;
883 
884     return  c;
885 }
886 
887 
888 STATIC
889 VOID
PITEM(IN OUT PRINT_STATE * ps)890 PITEM (
891     IN OUT PRINT_STATE  *ps
892     )
893 {
894     UINTN               Len, i;
895     PRINT_ITEM          *Item;
896     CHAR16              c;
897 
898     // Get the length of the item
899     Item = ps->Item;
900     Item->Item.Index = 0;
901     while (Item->Item.Index < Item->FieldWidth) {
902         c = PGETC(&Item->Item);
903         if (!c) {
904             Item->Item.Index -= 1;
905             break;
906         }
907     }
908     Len = Item->Item.Index;
909 
910     // if there is no item field width, use the items width
911     if (Item->FieldWidth == (UINTN) -1) {
912         Item->FieldWidth = Len;
913     }
914 
915     // if item is larger then width, update width
916     if (Len > Item->Width) {
917         Item->Width = Len;
918     }
919 
920 
921     // if pad field before, add pad char
922     if (Item->PadBefore) {
923         for (i=Item->Width; i < Item->FieldWidth; i+=1) {
924             PPUTC (ps, ' ');
925         }
926     }
927 
928     // pad item
929     for (i=Len; i < Item->Width; i++) {
930         PPUTC (ps, Item->Pad);
931     }
932 
933     // add the item
934     Item->Item.Index=0;
935     while (Item->Item.Index < Len) {
936         PPUTC (ps, PGETC(&Item->Item));
937     }
938 
939     // If pad at the end, add pad char
940     if (!Item->PadBefore) {
941         for (i=Item->Width; i < Item->FieldWidth; i+=1) {
942             PPUTC (ps, ' ');
943         }
944     }
945 }
946 
947 
948 STATIC
949 UINTN
_Print(IN PRINT_STATE * ps)950 _Print (
951     IN PRINT_STATE     *ps
952     )
953 /*++
954 
955 Routine Description:
956 
957     %w.lF   -   w = width
958                 l = field width
959                 F = format of arg
960 
961   Args F:
962     0       -   pad with zeros
963     -       -   justify on left (default is on right)
964     ,       -   add comma's to field
965     *       -   width provided on stack
966     n       -   Set output attribute to normal (for this field only)
967     h       -   Set output attribute to highlight (for this field only)
968     e       -   Set output attribute to error (for this field only)
969     l       -   Value is 64 bits
970 
971     a       -   ascii string
972     s       -   unicode string
973     X       -   fixed 8 byte value in hex
974     x       -   hex value
975     d       -   value as decimal
976     c       -   Unicode char
977     t       -   EFI time structure
978     g       -   Pointer to GUID
979     r       -   EFI status code (result code)
980 
981     N       -   Set output attribute to normal
982     H       -   Set output attribute to highlight
983     E       -   Set output attribute to error
984     %       -   Print a %
985 
986 Arguments:
987 
988     SystemTable     - The system table
989 
990 Returns:
991 
992     Number of charactors written
993 
994 --*/
995 {
996     CHAR16          c;
997     UINTN           Attr;
998     PRINT_ITEM      Item;
999     CHAR16          Buffer[PRINT_STRING_LEN];
1000 
1001     ps->Len = 0;
1002     ps->Buffer = Buffer;
1003     ps->Pos = Buffer;
1004     ps->End = Buffer + PRINT_STRING_LEN - 1;
1005     ps->Item = &Item;
1006 
1007     ps->fmt.Index = 0;
1008     while ((c = PGETC(&ps->fmt))) {
1009 
1010         if (c != '%') {
1011             PPUTC ( ps, c );
1012             continue;
1013         }
1014 
1015         // setup for new item
1016         Item.FieldWidth = (UINTN) -1;
1017         Item.Width = 0;
1018         Item.WidthParse = &Item.Width;
1019         Item.Pad = ' ';
1020         Item.PadBefore = TRUE;
1021         Item.Comma = FALSE;
1022         Item.Long = FALSE;
1023         Item.Item.Ascii = FALSE;
1024         Item.Item.pw = NULL;
1025         ps->RestoreAttr = 0;
1026         Attr = 0;
1027 
1028         while ((c = PGETC(&ps->fmt))) {
1029 
1030             switch (c) {
1031 
1032             case '%':
1033                 //
1034                 // %% -> %
1035                 //
1036                 Item.Item.pw = Item.Scratch;
1037                 Item.Item.pw[0] = '%';
1038                 Item.Item.pw[1] = 0;
1039                 break;
1040 
1041             case '0':
1042                 Item.Pad = '0';
1043                 break;
1044 
1045             case '-':
1046                 Item.PadBefore = FALSE;
1047                 break;
1048 
1049             case ',':
1050                 Item.Comma = TRUE;
1051                 break;
1052 
1053             case '.':
1054                 Item.WidthParse = &Item.FieldWidth;
1055                 break;
1056 
1057             case '*':
1058                 *Item.WidthParse = va_arg(ps->args, UINTN);
1059                 break;
1060 
1061             case '1':
1062             case '2':
1063             case '3':
1064             case '4':
1065             case '5':
1066             case '6':
1067             case '7':
1068             case '8':
1069             case '9':
1070                 *Item.WidthParse = 0;
1071                 do {
1072                     *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
1073                     c = PGETC(&ps->fmt);
1074                 } while (c >= '0'  &&  c <= '9') ;
1075                 ps->fmt.Index -= 1;
1076                 break;
1077 
1078             case 'a':
1079                 Item.Item.pc = va_arg(ps->args, CHAR8 *);
1080                 Item.Item.Ascii = TRUE;
1081                 if (!Item.Item.pc) {
1082                     Item.Item.pc = (CHAR8 *)"(null)";
1083                 }
1084                 break;
1085 
1086             case 's':
1087                 Item.Item.pw = va_arg(ps->args, CHAR16 *);
1088                 if (!Item.Item.pw) {
1089                     Item.Item.pw = L"(null)";
1090                 }
1091                 break;
1092 
1093             case 'c':
1094                 Item.Item.pw = Item.Scratch;
1095                 Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
1096                 Item.Item.pw[1] = 0;
1097                 break;
1098 
1099             case 'l':
1100                 Item.Long = TRUE;
1101                 break;
1102 
1103             case 'X':
1104                 Item.Width = Item.Long ? 16 : 8;
1105                 Item.Pad = '0';
1106             case 'x':
1107                 Item.Item.pw = Item.Scratch;
1108                 ValueToHex (
1109                     Item.Item.pw,
1110                     Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1111                     );
1112 
1113                 break;
1114 
1115 
1116             case 'g':
1117                 Item.Item.pw = Item.Scratch;
1118                 GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
1119                 break;
1120 
1121             case 'd':
1122                 Item.Item.pw = Item.Scratch;
1123                 ValueToString (
1124                     Item.Item.pw,
1125                     Item.Comma,
1126                     Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1127                     );
1128                 break
1129                     ;
1130             case 't':
1131                 Item.Item.pw = Item.Scratch;
1132                 TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
1133                 break;
1134 
1135             case 'r':
1136                 Item.Item.pw = Item.Scratch;
1137                 StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
1138                 break;
1139 
1140             case 'n':
1141                 PSETATTR(ps, ps->AttrNorm);
1142                 break;
1143 
1144             case 'h':
1145                 PSETATTR(ps, ps->AttrHighlight);
1146                 break;
1147 
1148             case 'e':
1149                 PSETATTR(ps, ps->AttrError);
1150                 break;
1151 
1152             case 'N':
1153                 Attr = ps->AttrNorm;
1154                 break;
1155 
1156             case 'H':
1157                 Attr = ps->AttrHighlight;
1158                 break;
1159 
1160             case 'E':
1161                 Attr = ps->AttrError;
1162                 break;
1163 
1164             default:
1165                 Item.Item.pw = Item.Scratch;
1166                 Item.Item.pw[0] = '?';
1167                 Item.Item.pw[1] = 0;
1168                 break;
1169             }
1170 
1171             // if we have an Item
1172             if (Item.Item.pw) {
1173                 PITEM (ps);
1174                 break;
1175             }
1176 
1177             // if we have an Attr set
1178             if (Attr) {
1179                 PSETATTR(ps, Attr);
1180                 ps->RestoreAttr = 0;
1181                 break;
1182             }
1183         }
1184 
1185         if (ps->RestoreAttr) {
1186             PSETATTR(ps, ps->RestoreAttr);
1187         }
1188     }
1189 
1190     // Flush buffer
1191     PFLUSH (ps);
1192     return ps->Len;
1193 }
1194 
1195 STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
1196                       '8','9','A','B','C','D','E','F'};
1197 
1198 VOID
ValueToHex(IN CHAR16 * Buffer,IN UINT64 v)1199 ValueToHex (
1200     IN CHAR16   *Buffer,
1201     IN UINT64   v
1202     )
1203 {
1204     CHAR8           str[30], *p1;
1205     CHAR16          *p2;
1206 
1207     if (!v) {
1208         Buffer[0] = '0';
1209         Buffer[1] = 0;
1210         return ;
1211     }
1212 
1213     p1 = str;
1214     p2 = Buffer;
1215 
1216     while (v) {
1217         *(p1++) = Hex[v & 0xf];
1218         v = RShiftU64 (v, 4);
1219     }
1220 
1221     while (p1 != str) {
1222         *(p2++) = *(--p1);
1223     }
1224     *p2 = 0;
1225 }
1226 
1227 
1228 VOID
ValueToString(IN CHAR16 * Buffer,IN BOOLEAN Comma,IN INT64 v)1229 ValueToString (
1230     IN CHAR16   *Buffer,
1231     IN BOOLEAN  Comma,
1232     IN INT64    v
1233     )
1234 {
1235     STATIC CHAR8 ca[] = {  3, 1, 2 };
1236     CHAR8        str[40], *p1;
1237     CHAR16       *p2;
1238     UINTN        c, r;
1239 
1240     if (!v) {
1241         Buffer[0] = '0';
1242         Buffer[1] = 0;
1243         return ;
1244     }
1245 
1246     p1 = str;
1247     p2 = Buffer;
1248 
1249     if (v < 0) {
1250         *(p2++) = '-';
1251         v = -v;
1252     }
1253 
1254     while (v) {
1255         v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
1256         *(p1++) = (CHAR8)r + '0';
1257     }
1258 
1259     c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
1260     while (p1 != str) {
1261 
1262         c -= 1;
1263         if (!c) {
1264             *(p2++) = ',';
1265             c = 3;
1266         }
1267 
1268         *(p2++) = *(--p1);
1269     }
1270     *p2 = 0;
1271 }
1272 
1273 VOID
TimeToString(OUT CHAR16 * Buffer,IN EFI_TIME * Time)1274 TimeToString (
1275     OUT CHAR16      *Buffer,
1276     IN EFI_TIME     *Time
1277     )
1278 {
1279     UINTN       Hour, Year;
1280     CHAR16      AmPm;
1281 
1282     AmPm = 'a';
1283     Hour = Time->Hour;
1284     if (Time->Hour == 0) {
1285         Hour = 12;
1286     } else if (Time->Hour >= 12) {
1287         AmPm = 'p';
1288         if (Time->Hour >= 13) {
1289             Hour -= 12;
1290         }
1291     }
1292 
1293     Year = Time->Year % 100;
1294 
1295     // bugbug: for now just print it any old way
1296     SPrint (Buffer, 0, L"%02d/%02d/%02d  %02d:%02d%c",
1297         Time->Month,
1298         Time->Day,
1299         Year,
1300         Hour,
1301         Time->Minute,
1302         AmPm
1303         );
1304 }
1305 
1306 
1307 
1308 
1309 VOID
DumpHex(IN UINTN Indent,IN UINTN Offset,IN UINTN DataSize,IN VOID * UserData)1310 DumpHex (
1311     IN UINTN        Indent,
1312     IN UINTN        Offset,
1313     IN UINTN        DataSize,
1314     IN VOID         *UserData
1315     )
1316 {
1317     CHAR8           *Data, Val[50], Str[20], c;
1318     UINTN           Size, Index;
1319 
1320     UINTN           ScreenCount;
1321     UINTN           TempColumn;
1322     UINTN           ScreenSize;
1323     CHAR16          ReturnStr[1];
1324 
1325 
1326     uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
1327     ScreenCount = 0;
1328     ScreenSize -= 2;
1329 
1330     Data = UserData;
1331     while (DataSize) {
1332         Size = 16;
1333         if (Size > DataSize) {
1334             Size = DataSize;
1335         }
1336 
1337         for (Index=0; Index < Size; Index += 1) {
1338             c = Data[Index];
1339             Val[Index*3+0] = Hex[c>>4];
1340             Val[Index*3+1] = Hex[c&0xF];
1341             Val[Index*3+2] = (Index == 7)?'-':' ';
1342             Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
1343         }
1344 
1345         Val[Index*3] = 0;
1346         Str[Index] = 0;
1347         Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
1348 
1349         Data += Size;
1350         Offset += Size;
1351         DataSize -= Size;
1352 
1353         ScreenCount++;
1354         if (ScreenCount >= ScreenSize && ScreenSize != 0) {
1355             //
1356             // If ScreenSize == 0 we have the console redirected so don't
1357             //  block updates
1358             //
1359             ScreenCount = 0;
1360             Print (L"Press Enter to continue :");
1361             Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
1362             Print (L"\n");
1363         }
1364 
1365     }
1366 }
1367