Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/Libefi/efiPrint.c

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#include <efi.h>
18
19
20
21//
22//
23//
24
25
26#define PRINT_STRING_LEN 200
27#define PRINT_ITEM_BUFFER_LEN 100
28
29typedef struct {
30 BOOLEAN Ascii;
31 UINTN Index;
32 union {
33 CHAR16 *pw;
34 CHAR8 *pc;
35 } un;
36} POINTER;
37
38#define pwun.pw
39#define pcun.pc
40
41typedef struct _pitem {
42
43 POINTER Item;
44 CHAR16 Scratch[PRINT_ITEM_BUFFER_LEN];
45 UINTN Width;
46 UINTN FieldWidth;
47 UINTN *WidthParse;
48 CHAR16 Pad;
49 BOOLEAN PadBefore;
50 BOOLEAN Comma;
51 BOOLEAN Long;
52} PRINT_ITEM;
53
54
55typedef struct _pstate {
56 // Input
57 POINTER fmt;
58 va_list args;
59
60 // Output
61 CHAR16 *Buffer;
62 CHAR16 *End;
63 CHAR16 *Pos;
64 UINTN Len;
65
66 UINTN Attr;
67 UINTN RestoreAttr;
68
69 UINTN AttrNorm;
70 UINTN AttrHighlight;
71 UINTN AttrError;
72
73 INTN (*Output)(VOID *context, CHAR16 *str);
74 INTN (*SetAttr)(VOID *context, UINTN attr);
75 VOID *Context;
76
77 // Current item being formatted
78 struct _pitem *Item;
79} PRINT_STATE;
80
81
82//
83//
84//
85
86STATIC
87UINTN
88_Print (
89 IN PRINT_STATE *ps
90 );
91
92
93INTN
94_SPrint (
95 IN VOID *Context,
96 IN CHAR16 *Buffer
97 );
98
99INTN
100_PoolPrint (
101 IN VOID *Context,
102 IN CHAR16 *Buffer
103 );
104
105VOID
106_PoolCatPrint (
107 IN CHAR16 *fmt,
108 IN va_list args,
109 IN OUT POOL_PRINT *spc,
110 IN INTN (*Output)(VOID *context, CHAR16 *str)
111 );
112
113VOID
114_PoolCatPrint (
115 IN CHAR16 *fmt,
116 IN va_list args,
117 IN OUT POOL_PRINT *spc,
118 IN INTN (*Output)(VOID *context, CHAR16 *str)
119 )
120// Dispath function for SPrint, PoolPrint, and CatPrint
121{
122 PRINT_STATE ps;
123
124 ZeroMem (&ps, sizeof(ps));
125 ps.Output = Output;
126 ps.Context = spc;
127 ps.fmt.pw = fmt;
128 va_copy(ps.args, args);
129 _Print (&ps);
130 va_end(ps.args);
131}
132
133
134INTN
135_SPrint (
136 IN VOID *Context,
137 IN CHAR16 *Buffer
138 )
139// Append string worker for SPrint, PoolPrint and CatPrint
140{
141 UINTN len;
142 POOL_PRINT *spc;
143
144 spc = Context;
145 len = StrLen(Buffer);
146
147 //
148 // Is the string is over the max truncate it
149 //
150
151 if (spc->len + len > spc->maxlen) {
152 len = spc->maxlen - spc->len;
153 }
154
155 //
156 // Append the new text
157 //
158
159 CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16));
160 spc->len += len;
161
162 //
163 // Null terminate it
164 //
165
166 if (spc->len < spc->maxlen) {
167 spc->str[spc->len] = 0;
168 } else if (spc->maxlen) {
169 spc->str[spc->maxlen-1] = 0;
170 }
171
172 return 0;
173}
174
175
176INTN
177_PoolPrint (
178 IN VOID *Context,
179 IN CHAR16 *Buffer
180 )
181// Append string worker for PoolPrint and CatPrint
182{
183 UINTN newlen;
184 POOL_PRINT *spc;
185
186 spc = Context;
187 newlen = spc->len + StrLen(Buffer) + 1;
188
189 //
190 // Is the string is over the max, grow the buffer
191 //
192
193 if (newlen > spc->maxlen) {
194
195 //
196 // Grow the pool buffer
197 //
198
199 newlen += PRINT_STRING_LEN;
200 spc->maxlen = newlen;
201 spc->str = ReallocatePool (
202 spc->len * sizeof(CHAR16),
203 spc->maxlen * sizeof(CHAR16),
204 spc->str
205 );
206
207 if (!spc->str) {
208 spc->len = 0;
209 spc->maxlen = 0;
210 }
211 }
212
213 //
214 // Append the new text
215 //
216
217 return _SPrint (Context, Buffer);
218}
219
220
221
222
223UINTN
224SPrint (
225 OUT CHAR16 *Str,
226 IN UINTN StrSize,
227 IN CHAR16 *fmt,
228 ...
229 )
230/*++
231
232 Routine Description:
233
234 Prints a formatted unicode string to a buffer
235
236 Arguments:
237
238 Str - Output buffer to print the formatted string into
239
240 StrSize - Size of Str. String is truncated to this size.
241 A size of 0 means there is no limit
242
243 fmt - The format string
244
245 Returns:
246
247 String length returned in buffer
248
249 --*/
250{
251 POOL_PRINT spc;
252 va_list args;
253
254
255 va_start (args, fmt);
256 spc.str = Str;
257 spc.maxlen = StrSize / sizeof(CHAR16) - 1;
258 spc.len = 0;
259
260 _PoolCatPrint (fmt, args, &spc, _SPrint);
261 va_end (args);
262 return spc.len;
263}
264
265
266CHAR16 *
267PoolPrint (
268 IN CHAR16 *fmt,
269 ...
270 )
271/*++
272
273 Routine Description:
274
275 Prints a formatted unicode string to allocated pool. The caller
276 must free the resulting buffer.
277
278 Arguments:
279
280 fmt - The format string
281
282 Returns:
283
284 Allocated buffer with the formatted string printed in it.
285 The caller must free the allocated buffer. The buffer
286 allocation is not packed.
287
288 --*/
289{
290 POOL_PRINT spc;
291 va_list args;
292
293 ZeroMem (&spc, sizeof(spc));
294 va_start (args, fmt);
295 _PoolCatPrint (fmt, args, &spc, _PoolPrint);
296 va_end (args);
297 return spc.str;
298}
299
300
301
302CHAR16 *
303CatPrint (
304 IN OUT POOL_PRINT *Str,
305 IN CHAR16 *fmt,
306 ...
307 )
308/*++
309
310 Routine Description:
311
312 Concatenates a formatted unicode string to allocated pool.
313 The caller must free the resulting buffer.
314
315 Arguments:
316
317 Str - Tracks the allocated pool, size in use, and
318 amount of pool allocated.
319
320 fmt - The format string
321
322 Returns:
323
324 Allocated buffer with the formatted string printed in it.
325 The caller must free the allocated buffer. The buffer
326 allocation is not packed.
327
328 --*/
329{
330 va_list args;
331
332 va_start (args, fmt);
333 _PoolCatPrint (fmt, args, Str, _PoolPrint);
334 va_end (args);
335 return Str->str;
336}
337
338
339VOID
340TimeToString (
341 OUT CHAR16 *Buffer,
342 IN EFI_TIME *Time
343 )
344{
345 UINTN Hour, Year;
346 CHAR16 AmPm;
347
348 AmPm = 'a';
349 Hour = Time->Hour;
350 if (Time->Hour == 0) {
351 Hour = 12;
352 } else if (Time->Hour >= 12) {
353 AmPm = 'p';
354 if (Time->Hour >= 13) {
355 Hour -= 12;
356 }
357 }
358
359 Year = Time->Year % 100;
360
361 // bugbug: for now just print it any old way
362 SPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c",
363 Time->Month,
364 Time->Day,
365 Year,
366 Hour,
367 Time->Minute,
368 AmPm
369 );
370}
371
372STATIC
373VOID
374PFLUSH (
375 IN OUT PRINT_STATE *ps
376 )
377{
378 *ps->Pos = 0;
379 //if (IsLocalPrint(ps->Output))
380 ps->Output(ps->Context, ps->Buffer);
381 //else
382 //uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
383 ps->Pos = ps->Buffer;
384}
385
386STATIC
387VOID
388PSETATTR (
389 IN OUT PRINT_STATE *ps,
390 IN UINTN Attr
391 )
392{
393 PFLUSH (ps);
394
395 ps->RestoreAttr = ps->Attr;
396 //if (ps->SetAttr) {
397 // uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
398 //}
399
400 ps->Attr = Attr;
401}
402
403STATIC
404VOID
405PPUTC (
406 IN OUT PRINT_STATE *ps,
407 IN CHAR16 c
408 )
409{
410 // if this is a newline, add a carraige return
411 if (c == '\n') {
412 PPUTC (ps, '\r');
413 }
414
415 *ps->Pos = c;
416 ps->Pos += 1;
417 ps->Len += 1;
418
419 // if at the end of the buffer, flush it
420 if (ps->Pos >= ps->End) {
421 PFLUSH(ps);
422 }
423}
424
425
426STATIC
427CHAR16
428PGETC (
429 IN POINTER *p
430 )
431{
432 CHAR16 c;
433
434 c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
435 p->Index += 1;
436
437 return c;
438}
439
440
441STATIC
442VOID
443PITEM (
444 IN OUT PRINT_STATE *ps
445 )
446{
447 UINTN Len, i;
448 PRINT_ITEM *Item;
449 CHAR16 c;
450
451 // Get the length of the item
452 Item = ps->Item;
453 Item->Item.Index = 0;
454 while (Item->Item.Index < Item->FieldWidth) {
455 c = PGETC(&Item->Item);
456 if (!c) {
457 Item->Item.Index -= 1;
458 break;
459 }
460 }
461 Len = Item->Item.Index;
462
463 // if there is no item field width, use the items width
464 if (Item->FieldWidth == (UINTN) -1) {
465 Item->FieldWidth = Len;
466 }
467
468 // if item is larger then width, update width
469 if (Len > Item->Width) {
470 Item->Width = Len;
471 }
472
473
474 // if pad field before, add pad char
475 if (Item->PadBefore) {
476 for (i=Item->Width; i < Item->FieldWidth; i+=1) {
477 PPUTC (ps, ' ');
478 }
479 }
480
481 // pad item
482 for (i=Len; i < Item->Width; i++) {
483 PPUTC (ps, Item->Pad);
484 }
485
486 // add the item
487 Item->Item.Index=0;
488 while (Item->Item.Index < Len) {
489 PPUTC (ps, PGETC(&Item->Item));
490 }
491
492 // If pad at the end, add pad char
493 if (!Item->PadBefore) {
494 for (i=Item->Width; i < Item->FieldWidth; i+=1) {
495 PPUTC (ps, ' ');
496 }
497 }
498}
499
500STATIC
501UINTN
502_Print (
503 IN PRINT_STATE *ps
504 )
505/*++
506
507 Routine Description:
508
509 %w.lF - w = width
510 l = field width
511 F = format of arg
512
513 Args F:
514 0 - pad with zeros
515 - - justify on left (default is on right)
516 , - add comma's to field
517 * - width provided on stack
518 n - Set output attribute to normal (for this field only)
519 h - Set output attribute to highlight (for this field only)
520 e - Set output attribute to error (for this field only)
521 l - Value is 64 bits
522
523 a - ascii string
524 s - unicode string
525 X - fixed 8 byte value in hex
526 x - hex value
527 d - value as decimal
528 c - Unicode char
529 t - EFI time structure
530 g - Pointer to GUID
531 r - EFI status code (result code)
532
533 N - Set output attribute to normal
534 H - Set output attribute to highlight
535 E - Set output attribute to error
536 % - Print a %
537
538 Arguments:
539
540 SystemTable - The system table
541
542 Returns:
543
544 Number of charactors written
545
546 --*/
547{
548 CHAR16 c;
549 UINTN Attr;
550 PRINT_ITEM Item;
551 CHAR16 Buffer[PRINT_STRING_LEN];
552
553 ps->Len = 0;
554 ps->Buffer = Buffer;
555 ps->Pos = Buffer;
556 ps->End = Buffer + PRINT_STRING_LEN - 1;
557 ps->Item = &Item;
558
559 ps->fmt.Index = 0;
560 while ((c = PGETC(&ps->fmt))) {
561
562 if (c != '%') {
563 PPUTC ( ps, c );
564 continue;
565 }
566
567 // setup for new item
568 Item.FieldWidth = (UINTN) -1;
569 Item.Width = 0;
570 Item.WidthParse = &Item.Width;
571 Item.Pad = ' ';
572 Item.PadBefore = TRUE;
573 Item.Comma = FALSE;
574 Item.Long = FALSE;
575 Item.Item.Ascii = FALSE;
576 Item.Item.pw = NULL;
577 ps->RestoreAttr = 0;
578 Attr = 0;
579
580 while ((c = PGETC(&ps->fmt))) {
581
582 switch (c) {
583
584 case '%':
585 //
586 // %% -> %
587 //
588 Item.Item.pw = Item.Scratch;
589 Item.Item.pw[0] = '%';
590 Item.Item.pw[1] = 0;
591 break;
592
593 case '0':
594 Item.Pad = '0';
595 break;
596
597 case '-':
598 Item.PadBefore = FALSE;
599 break;
600
601 case ',':
602 Item.Comma = TRUE;
603 break;
604
605 case '.':
606 Item.WidthParse = &Item.FieldWidth;
607 break;
608
609 case '*':
610 *Item.WidthParse = va_arg(ps->args, UINTN);
611 break;
612
613 case '1':
614 case '2':
615 case '3':
616 case '4':
617 case '5':
618 case '6':
619 case '7':
620 case '8':
621 case '9':
622 *Item.WidthParse = 0;
623 do {
624 *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
625 c = PGETC(&ps->fmt);
626 } while (c >= '0' && c <= '9') ;
627 ps->fmt.Index -= 1;
628 break;
629
630 case 'a':
631 Item.Item.pc = va_arg(ps->args, CHAR8 *);
632 Item.Item.Ascii = TRUE;
633 if (!Item.Item.pc) {
634 Item.Item.pc = (CHAR8 *)"(null)";
635 }
636 break;
637
638 case 's':
639 Item.Item.pw = va_arg(ps->args, CHAR16 *);
640 if (!Item.Item.pw) {
641 Item.Item.pw = L"(null)";
642 }
643 break;
644
645 case 'c':
646 Item.Item.pw = Item.Scratch;
647 Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
648 Item.Item.pw[1] = 0;
649 break;
650
651 case 'l':
652 Item.Long = TRUE;
653 break;
654
655 case 'X':
656 Item.Width = Item.Long ? 16 : 8;
657 Item.Pad = '0';
658 case 'x':
659 Item.Item.pw = Item.Scratch;
660 ValueToHex (
661 Item.Item.pw,
662 Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
663 );
664
665 break;
666
667
668 case 'g':
669 //Item.Item.pw = Item.Scratch;
670 //GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
671 break;
672
673 case 'd':
674 Item.Item.pw = Item.Scratch;
675 ValueToString (
676 Item.Item.pw,
677 Item.Comma,
678 Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
679 );
680 break
681 ;
682 case 't':
683 Item.Item.pw = Item.Scratch;
684 TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
685 break;
686
687 case 'r':
688 Item.Item.pw = Item.Scratch;
689 StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
690 break;
691
692 case 'n':
693 PSETATTR(ps, ps->AttrNorm);
694 break;
695
696 case 'h':
697 PSETATTR(ps, ps->AttrHighlight);
698 break;
699
700 case 'e':
701 PSETATTR(ps, ps->AttrError);
702 break;
703
704 case 'N':
705 Attr = ps->AttrNorm;
706 break;
707
708 case 'H':
709 Attr = ps->AttrHighlight;
710 break;
711
712 case 'E':
713 Attr = ps->AttrError;
714 break;
715
716 default:
717 Item.Item.pw = Item.Scratch;
718 Item.Item.pw[0] = '?';
719 Item.Item.pw[1] = 0;
720 break;
721 }
722
723 // if we have an Item
724 if (Item.Item.pw) {
725 PITEM (ps);
726 break;
727 }
728
729 // if we have an Attr set
730 if (Attr) {
731 PSETATTR(ps, Attr);
732 ps->RestoreAttr = 0;
733 break;
734 }
735 }
736
737 if (ps->RestoreAttr) {
738 PSETATTR(ps, ps->RestoreAttr);
739 }
740 }
741
742 // Flush buffer
743 PFLUSH (ps);
744 return ps->Len;
745}
746
747STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
748 '8','9','A','B','C','D','E','F'};
749
750VOID
751ValueToHex (
752 IN CHAR16 *Buffer,
753 IN UINT64 v
754 )
755{
756 CHAR8 str[30], *p1;
757 CHAR16 *p2;
758
759 if (!v) {
760 Buffer[0] = '0';
761 Buffer[1] = 0;
762 return ;
763 }
764
765 p1 = str;
766 p2 = Buffer;
767
768 while (v) {
769 *(p1++) = Hex[v & 0xf];
770 v = RShiftU64 (v, 4);
771 }
772
773 while (p1 != str) {
774 *(p2++) = *(--p1);
775 }
776 *p2 = 0;
777}
778
779
780VOID
781ValueToString (
782 IN CHAR16 *Buffer,
783 IN BOOLEAN Comma,
784 IN INT64 v
785 )
786{
787 STATIC CHAR8 ca[] = { 3, 1, 2 };
788 CHAR8 str[40], *p1;
789 CHAR16 *p2;
790 UINTN c, r;
791
792 if (!v) {
793 Buffer[0] = '0';
794 Buffer[1] = 0;
795 return ;
796 }
797
798 p1 = str;
799 p2 = Buffer;
800
801 if (v < 0) {
802 *(p2++) = '-';
803 v = -v;
804 }
805
806 while (v) {
807 v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
808 *(p1++) = (CHAR8)r + '0';
809 }
810
811 c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
812 while (p1 != str) {
813
814 c -= 1;
815 if (!c) {
816 *(p2++) = ',';
817 c = 3;
818 }
819
820 *(p2++) = *(--p1);
821 }
822 *p2 = 0;
823}
824
825struct {
826 EFI_STATUS Code;
827 CHAR_W *Desc;
828} ErrorCodeTable[] = {
829{ EFI_SUCCESS, L"Success"},
830{ EFI_LOAD_ERROR, L"Load Error"},
831{ EFI_INVALID_PARAMETER, L"Invalid Parameter"},
832{ EFI_UNSUPPORTED, L"Unsupported"},
833{ EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size"},
834{ EFI_BUFFER_TOO_SMALL, L"Buffer Too Small"},
835{ EFI_NOT_READY, L"Not Ready"},
836{ EFI_DEVICE_ERROR, L"Device Error"},
837{ EFI_WRITE_PROTECTED, L"Write Protected"},
838{ EFI_OUT_OF_RESOURCES, L"Out of Resources"},
839{ EFI_VOLUME_CORRUPTED, L"Volume Corrupt"},
840{ EFI_VOLUME_FULL, L"Volume Full"},
841{ EFI_NO_MEDIA, L"No Media"},
842{ EFI_MEDIA_CHANGED, L"Media changed"},
843{ EFI_NOT_FOUND, L"Not Found"},
844{ EFI_ACCESS_DENIED, L"Access Denied"},
845{ EFI_NO_RESPONSE, L"No Response"},
846{ EFI_NO_MAPPING, L"No mapping"},
847{ EFI_TIMEOUT, L"Time out"},
848{ EFI_NOT_STARTED, L"Not started"},
849{ EFI_ALREADY_STARTED, L"Already started"},
850{ EFI_ABORTED, L"Aborted"},
851{ EFI_ICMP_ERROR, L"ICMP Error"},
852{ EFI_TFTP_ERROR, L"TFTP Error"},
853{ EFI_PROTOCOL_ERROR, L"Protocol Error"},
854
855// warnings
856{ EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure"},
857{ EFI_WARN_WRITE_FAILURE, L"Warning Write Failure"},
858{ EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small"},
859{ 0, NULL}
860} ;
861
862
863VOID
864StatusToString (
865 OUT CHAR16 *Buffer,
866 IN EFI_STATUS Status
867 )
868{
869 UINTN Index;
870
871 for (Index = 0; ErrorCodeTable[Index].Desc; Index +=1) {
872 if (ErrorCodeTable[Index].Code == Status) {
873 StrCpy (Buffer, ErrorCodeTable[Index].Desc);
874 return;
875 }
876 }
877
878 SPrint (Buffer, 0, L"%X", Status);
879}
880

Archive Download this file

Revision: 2182