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