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