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