3 Copyright (c) 1998 Intel Corporation
19 #include "efistdarg.h" // !!!
22 // Declare runtime functions
27 #pragma RUNTIME_CODE(DbgPrint)
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)
43 #endif /* !defined(__GNUC__) */
51 #define PRINT_STRING_LEN 200
52 #define PRINT_ITEM_BUFFER_LEN 100
66 typedef struct _pitem {
69 CHAR16 Scratch[PRINT_ITEM_BUFFER_LEN];
80 typedef struct _pstate {
98 INTN EFIAPI (*Output)(VOID *context, CHAR16 *str);
99 INTN EFIAPI (*SetAttr)(VOID *context, UINTN attr);
102 // Current item being formatted
107 // Internal fucntions
121 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
137 IN OUT PRINT_STATE *ps
143 IN OUT PRINT_STATE *ps,
150 IN OUT PRINT_STATE *ps
162 IN OUT PRINT_STATE *ps,
192 Prints a formatted unicode string to the default StandardError console
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
204 Length of string printed to the StandardError console
208 SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
213 UINTN SavedAttribute;
216 if (!(EFIDebug & mask)) {
220 va_start (args, fmt);
221 ZeroMem (&ps, sizeof(ps));
226 va_copy(ps.args, args);
227 ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED);
229 DbgOut = LibRuntimeDebugOut;
236 ps.Attr = DbgOut->Mode->Attribute;
238 ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN)) DbgOut->SetAttribute;
241 SavedAttribute = ps.Attr;
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);
251 attr = ps.AttrHighlight;
254 if (mask & D_ERROR) {
260 ps.SetAttr (ps.Context, attr);
269 // Restore original attributes
273 ps.SetAttr (ps.Context, SavedAttribute);
281 IsLocalPrint(void *func)
283 if (func == _DbgOut || func == _SPrint || func == _PoolPrint)
294 // Append string worker for DbgPrint
296 SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
299 // if (!DbgOut && ST && ST->ConOut) {
300 // DbgOut = ST->ConOut;
304 if (IsLocalPrint(DbgOut->OutputString))
305 DbgOut->OutputString(DbgOut, Buffer);
307 uefi_call_wrapper(DbgOut->OutputString, 2, DbgOut, Buffer);
318 // Append string worker for SPrint, PoolPrint and CatPrint
324 len = StrLen(Buffer);
327 // Is the string is over the max truncate it
330 if (spc->len + len > spc->maxlen) {
331 len = spc->maxlen - spc->len;
335 // Append the new text
338 CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16));
345 if (spc->len < spc->maxlen) {
346 spc->str[spc->len] = 0;
347 } else if (spc->maxlen) {
348 spc->str[spc->maxlen-1] = 0;
360 // Append string worker for PoolPrint and CatPrint
366 newlen = spc->len + StrLen(Buffer) + 1;
369 // Is the string is over the max, grow the buffer
372 if (newlen > spc->maxlen) {
375 // Grow the pool buffer
378 newlen += PRINT_STRING_LEN;
379 spc->maxlen = newlen;
380 spc->str = ReallocatePool (
382 spc->len * sizeof(CHAR16),
383 spc->maxlen * sizeof(CHAR16)
393 // Append the new text
396 return _SPrint (Context, Buffer);
405 IN OUT POOL_PRINT *spc,
406 IN INTN EFIAPI (*Output)(VOID *context, CHAR16 *str)
408 // Dispath function for SPrint, PoolPrint, and CatPrint
412 ZeroMem (&ps, sizeof(ps));
416 va_copy(ps.args, args);
434 Prints a formatted unicode string to a buffer
438 Str - Output buffer to print the formatted string into
440 StrSize - Size of Str. String is truncated to this size.
441 A size of 0 means there is no limit
443 fmt - The format string
447 String length returned in buffer
455 va_start (args, fmt);
457 spc.maxlen = StrSize / sizeof(CHAR16) - 1;
460 _PoolCatPrint (fmt, args, &spc, _SPrint);
475 Prints a formatted unicode string to allocated pool. The caller
476 must free the resulting buffer.
480 fmt - The format string
484 Allocated buffer with the formatted string printed in it.
485 The caller must free the allocated buffer. The buffer
486 allocation is not packed.
493 ZeroMem (&spc, sizeof(spc));
494 va_start (args, fmt);
495 _PoolCatPrint (fmt, args, &spc, _PoolPrint);
504 IN OUT POOL_PRINT *Str,
512 Concatenates a formatted unicode string to allocated pool.
513 The caller must free the resulting buffer.
517 Str - Tracks the allocated pool, size in use, and
518 amount of pool allocated.
520 fmt - The format string
524 Allocated buffer with the formatted string printed in it.
525 The caller must free the allocated buffer. The buffer
526 allocation is not packed.
532 va_start (args, fmt);
533 _PoolCatPrint (fmt, args, Str, _PoolPrint);
549 Prints a formatted unicode string to the default console
557 Length of string printed to the console
564 va_start (args, fmt);
565 back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
579 Prints a formatted unicode string to the default console using a va_list
587 Length of string printed to the console
591 return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
606 Prints a formatted unicode string to the default console, at
607 the supplied cursor position
611 Column, Row - The cursor position to print the string at
617 Length of string printed to the console
624 va_start (args, fmt);
625 back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
633 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
641 Prints a formatted unicode string to the specified console
645 Out - The console to print the string too
651 Length of string printed to the console
658 va_start (args, fmt);
659 back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
667 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
677 Prints a formatted unicode string to the specified console, at
678 the supplied cursor position
682 Out - The console to print the string too
684 Column, Row - The cursor position to print the string at
690 Length of string printed to the console
697 va_start (args, fmt);
698 back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
708 IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
713 // Display string worker for: Print, PrintAt, IPrint, IPrintAt
718 ZeroMem (&ps, sizeof(ps));
720 ps.Output = (INTN EFIAPI (*)(VOID *, CHAR16 *)) Out->OutputString;
721 ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN)) Out->SetAttribute;
722 ps.Attr = Out->Mode->Attribute;
724 back = (ps.Attr >> 4) & 0xF;
725 ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
726 ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
727 ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
736 va_copy(ps.args, args);
738 if (Column != (UINTN) -1) {
739 uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row);
757 For those whom really can't deal with unicode, a print
758 function that takes an ascii format string
762 fmt - ascii format string
766 Length of string printed to the console
774 va_start (args, fmt);
775 back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
784 IN OUT PRINT_STATE *ps
788 if (IsLocalPrint(ps->Output))
789 ps->Output(ps->Context, ps->Buffer);
791 uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
792 ps->Pos = ps->Buffer;
798 IN OUT PRINT_STATE *ps,
804 ps->RestoreAttr = ps->Attr;
806 uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
815 IN OUT PRINT_STATE *ps,
819 // if this is a newline, add a carraige return
828 // if at the end of the buffer, flush it
829 if (ps->Pos >= ps->End) {
843 c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
853 IN OUT PRINT_STATE *ps
860 // Get the length of the item
862 Item->Item.Index = 0;
863 while (Item->Item.Index < Item->FieldWidth) {
864 c = PGETC(&Item->Item);
866 Item->Item.Index -= 1;
870 Len = Item->Item.Index;
872 // if there is no item field width, use the items width
873 if (Item->FieldWidth == (UINTN) -1) {
874 Item->FieldWidth = Len;
877 // if item is larger then width, update width
878 if (Len > Item->Width) {
883 // if pad field before, add pad char
884 if (Item->PadBefore) {
885 for (i=Item->Width; i < Item->FieldWidth; i+=1) {
891 for (i=Len; i < Item->Width; i++) {
892 PPUTC (ps, Item->Pad);
897 while (Item->Item.Index < Len) {
898 PPUTC (ps, PGETC(&Item->Item));
901 // If pad at the end, add pad char
902 if (!Item->PadBefore) {
903 for (i=Item->Width; i < Item->FieldWidth; i+=1) {
925 - - justify on left (default is on right)
926 , - add comma's to field
927 * - width provided on stack
928 n - Set output attribute to normal (for this field only)
929 h - Set output attribute to highlight (for this field only)
930 e - Set output attribute to error (for this field only)
935 X - fixed 8 byte value in hex
939 t - EFI time structure
941 r - EFI status code (result code)
943 N - Set output attribute to normal
944 H - Set output attribute to highlight
945 E - Set output attribute to error
950 SystemTable - The system table
954 Number of charactors written
961 CHAR16 Buffer[PRINT_STRING_LEN];
966 ps->End = Buffer + PRINT_STRING_LEN - 1;
970 while ((c = PGETC(&ps->fmt))) {
977 // setup for new item
978 Item.FieldWidth = (UINTN) -1;
980 Item.WidthParse = &Item.Width;
982 Item.PadBefore = TRUE;
985 Item.Item.Ascii = FALSE;
990 while ((c = PGETC(&ps->fmt))) {
998 Item.Item.pw = Item.Scratch;
999 Item.Item.pw[0] = '%';
1000 Item.Item.pw[1] = 0;
1008 Item.PadBefore = FALSE;
1016 Item.WidthParse = &Item.FieldWidth;
1020 *Item.WidthParse = va_arg(ps->args, UINTN);
1032 *Item.WidthParse = 0;
1034 *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
1035 c = PGETC(&ps->fmt);
1036 } while (c >= '0' && c <= '9') ;
1041 Item.Item.pc = va_arg(ps->args, CHAR8 *);
1042 Item.Item.Ascii = TRUE;
1043 if (!Item.Item.pc) {
1044 Item.Item.pc = (CHAR8 *)"(null)";
1049 Item.Item.pw = va_arg(ps->args, CHAR16 *);
1050 if (!Item.Item.pw) {
1051 Item.Item.pw = L"(null)";
1056 Item.Item.pw = Item.Scratch;
1057 Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
1058 Item.Item.pw[1] = 0;
1066 Item.Width = Item.Long ? 16 : 8;
1069 Item.Item.pw = Item.Scratch;
1072 Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1079 Item.Item.pw = Item.Scratch;
1080 GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
1084 Item.Item.pw = Item.Scratch;
1088 Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1093 Item.Item.pw = Item.Scratch;
1094 TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
1098 Item.Item.pw = Item.Scratch;
1099 StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
1103 PSETATTR(ps, ps->AttrNorm);
1107 PSETATTR(ps, ps->AttrHighlight);
1111 PSETATTR(ps, ps->AttrError);
1115 Attr = ps->AttrNorm;
1119 Attr = ps->AttrHighlight;
1123 Attr = ps->AttrError;
1127 Item.Item.pw = Item.Scratch;
1128 Item.Item.pw[0] = '?';
1129 Item.Item.pw[1] = 0;
1133 // if we have an Item
1139 // if we have an Attr set
1142 ps->RestoreAttr = 0;
1147 if (ps->RestoreAttr) {
1148 PSETATTR(ps, ps->RestoreAttr);
1157 STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
1158 '8','9','A','B','C','D','E','F'};
1179 *(p1++) = Hex[v & 0xf];
1180 v = RShiftU64 (v, 4);
1197 STATIC CHAR8 ca[] = { 3, 1, 2 };
1217 v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
1218 *(p1++) = (CHAR8)r + '0';
1221 c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
1246 if (Time->Hour == 0) {
1248 } else if (Time->Hour >= 12) {
1250 if (Time->Hour >= 13) {
1255 Year = Time->Year % 100;
1257 // bugbug: for now just print it any old way
1258 SPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c",
1279 CHAR8 *Data, Val[50], Str[20], c;
1285 CHAR16 ReturnStr[1];
1288 uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
1295 if (Size > DataSize) {
1299 for (Index=0; Index < Size; Index += 1) {
1301 Val[Index*3+0] = Hex[c>>4];
1302 Val[Index*3+1] = Hex[c&0xF];
1303 Val[Index*3+2] = (Index == 7)?'-':' ';
1304 Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
1309 Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
1316 if (ScreenCount >= ScreenSize && ScreenSize != 0) {
1318 // If ScreenSize == 0 we have the console redirected so don't
1322 Print (L"Press Enter to continue :");
1323 Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));