xref: /DragonStub/lib/print.c (revision 1acb1d9dae8192e72e3de7ac826f47263fe280c5)
1530d68baSNigel Croxon /*++
2530d68baSNigel Croxon 
3530d68baSNigel Croxon Copyright (c) 1998  Intel Corporation
4530d68baSNigel Croxon 
5530d68baSNigel Croxon Module Name:
6530d68baSNigel Croxon 
7530d68baSNigel Croxon     print.c
8530d68baSNigel Croxon 
9530d68baSNigel Croxon Abstract:
10530d68baSNigel Croxon 
11530d68baSNigel Croxon 
12530d68baSNigel Croxon 
13530d68baSNigel Croxon 
14530d68baSNigel Croxon Revision History
15530d68baSNigel Croxon 
16530d68baSNigel Croxon --*/
17530d68baSNigel Croxon 
18530d68baSNigel Croxon #include "lib.h"
19530d68baSNigel Croxon #include "efistdarg.h"                        // !!!
20530d68baSNigel Croxon 
21530d68baSNigel Croxon //
22530d68baSNigel Croxon // Declare runtime functions
23530d68baSNigel Croxon //
24530d68baSNigel Croxon 
25530d68baSNigel Croxon #ifdef RUNTIME_CODE
26530d68baSNigel Croxon #ifndef __GNUC__
27530d68baSNigel Croxon #pragma RUNTIME_CODE(DbgPrint)
28530d68baSNigel Croxon 
29530d68baSNigel Croxon // For debugging..
30530d68baSNigel Croxon 
31530d68baSNigel Croxon /*
32530d68baSNigel Croxon #pragma RUNTIME_CODE(_Print)
33530d68baSNigel Croxon #pragma RUNTIME_CODE(PFLUSH)
34530d68baSNigel Croxon #pragma RUNTIME_CODE(PSETATTR)
35530d68baSNigel Croxon #pragma RUNTIME_CODE(PPUTC)
36530d68baSNigel Croxon #pragma RUNTIME_CODE(PGETC)
37530d68baSNigel Croxon #pragma RUNTIME_CODE(PITEM)
38530d68baSNigel Croxon #pragma RUNTIME_CODE(ValueToHex)
39530d68baSNigel Croxon #pragma RUNTIME_CODE(ValueToString)
40530d68baSNigel Croxon #pragma RUNTIME_CODE(TimeToString)
41530d68baSNigel Croxon */
42530d68baSNigel Croxon 
43530d68baSNigel Croxon #endif /* !defined(__GNUC__) */
44530d68baSNigel Croxon #endif
45530d68baSNigel Croxon 
46530d68baSNigel Croxon //
47530d68baSNigel Croxon //
48530d68baSNigel Croxon //
49530d68baSNigel Croxon 
50530d68baSNigel Croxon 
51530d68baSNigel Croxon #define PRINT_STRING_LEN            200
52530d68baSNigel Croxon #define PRINT_ITEM_BUFFER_LEN       100
53530d68baSNigel Croxon 
54530d68baSNigel Croxon typedef struct {
55530d68baSNigel Croxon     BOOLEAN             Ascii;
56530d68baSNigel Croxon     UINTN               Index;
57530d68baSNigel Croxon     union {
58530d68baSNigel Croxon         CHAR16          *pw;
59530d68baSNigel Croxon         CHAR8           *pc;
60530d68baSNigel Croxon     } un;
61530d68baSNigel Croxon } POINTER;
62530d68baSNigel Croxon 
63530d68baSNigel Croxon #define pw	un.pw
64530d68baSNigel Croxon #define pc	un.pc
65530d68baSNigel Croxon 
66530d68baSNigel Croxon typedef struct _pitem {
67530d68baSNigel Croxon 
68530d68baSNigel Croxon     POINTER     Item;
69530d68baSNigel Croxon     CHAR16      Scratch[PRINT_ITEM_BUFFER_LEN];
70530d68baSNigel Croxon     UINTN       Width;
71530d68baSNigel Croxon     UINTN       FieldWidth;
72530d68baSNigel Croxon     UINTN       *WidthParse;
73530d68baSNigel Croxon     CHAR16      Pad;
74530d68baSNigel Croxon     BOOLEAN     PadBefore;
75530d68baSNigel Croxon     BOOLEAN     Comma;
76530d68baSNigel Croxon     BOOLEAN     Long;
77530d68baSNigel Croxon } PRINT_ITEM;
78530d68baSNigel Croxon 
79530d68baSNigel Croxon 
80530d68baSNigel Croxon typedef struct _pstate {
81530d68baSNigel Croxon     // Input
82530d68baSNigel Croxon     POINTER     fmt;
83530d68baSNigel Croxon     va_list     args;
84530d68baSNigel Croxon 
85530d68baSNigel Croxon     // Output
86530d68baSNigel Croxon     CHAR16      *Buffer;
87530d68baSNigel Croxon     CHAR16      *End;
88530d68baSNigel Croxon     CHAR16      *Pos;
89530d68baSNigel Croxon     UINTN       Len;
90530d68baSNigel Croxon 
91530d68baSNigel Croxon     UINTN       Attr;
92530d68baSNigel Croxon     UINTN       RestoreAttr;
93530d68baSNigel Croxon 
94530d68baSNigel Croxon     UINTN       AttrNorm;
95530d68baSNigel Croxon     UINTN       AttrHighlight;
96530d68baSNigel Croxon     UINTN       AttrError;
97530d68baSNigel Croxon 
9809027207SNigel Croxon     INTN        (EFIAPI *Output)(VOID *context, CHAR16 *str);
9909027207SNigel Croxon     INTN        (EFIAPI *SetAttr)(VOID *context, UINTN attr);
100530d68baSNigel Croxon     VOID        *Context;
101530d68baSNigel Croxon 
102530d68baSNigel Croxon     // Current item being formatted
103530d68baSNigel Croxon     struct _pitem  *Item;
104530d68baSNigel Croxon } PRINT_STATE;
105530d68baSNigel Croxon 
106530d68baSNigel Croxon //
107530d68baSNigel Croxon // Internal fucntions
108530d68baSNigel Croxon //
109530d68baSNigel Croxon 
110530d68baSNigel Croxon STATIC
111530d68baSNigel Croxon UINTN
112530d68baSNigel Croxon _Print (
113530d68baSNigel Croxon     IN PRINT_STATE     *ps
114530d68baSNigel Croxon     );
115530d68baSNigel Croxon 
116530d68baSNigel Croxon STATIC
117530d68baSNigel Croxon UINTN
118530d68baSNigel Croxon _IPrint (
119530d68baSNigel Croxon     IN UINTN                            Column,
120530d68baSNigel Croxon     IN UINTN                            Row,
121530d68baSNigel Croxon     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
122530d68baSNigel Croxon     IN CHAR16                           *fmt,
123530d68baSNigel Croxon     IN CHAR8                            *fmta,
124530d68baSNigel Croxon     IN va_list                          args
125530d68baSNigel Croxon     );
126530d68baSNigel Croxon 
127530d68baSNigel Croxon STATIC
128530d68baSNigel Croxon INTN EFIAPI
129530d68baSNigel Croxon _DbgOut (
130530d68baSNigel Croxon     IN VOID     *Context,
131530d68baSNigel Croxon     IN CHAR16   *Buffer
132530d68baSNigel Croxon     );
133530d68baSNigel Croxon 
134530d68baSNigel Croxon STATIC
135530d68baSNigel Croxon VOID
136530d68baSNigel Croxon PFLUSH (
137530d68baSNigel Croxon     IN OUT PRINT_STATE     *ps
138530d68baSNigel Croxon     );
139530d68baSNigel Croxon 
140530d68baSNigel Croxon STATIC
141530d68baSNigel Croxon VOID
142530d68baSNigel Croxon PPUTC (
143530d68baSNigel Croxon     IN OUT PRINT_STATE     *ps,
144530d68baSNigel Croxon     IN CHAR16              c
145530d68baSNigel Croxon     );
146530d68baSNigel Croxon 
147530d68baSNigel Croxon STATIC
148530d68baSNigel Croxon VOID
149530d68baSNigel Croxon PITEM (
150530d68baSNigel Croxon     IN OUT PRINT_STATE  *ps
151530d68baSNigel Croxon     );
152530d68baSNigel Croxon 
153530d68baSNigel Croxon STATIC
154530d68baSNigel Croxon CHAR16
155530d68baSNigel Croxon PGETC (
156530d68baSNigel Croxon     IN POINTER      *p
157530d68baSNigel Croxon     );
158530d68baSNigel Croxon 
159530d68baSNigel Croxon STATIC
160530d68baSNigel Croxon VOID
161530d68baSNigel Croxon PSETATTR (
162530d68baSNigel Croxon     IN OUT PRINT_STATE  *ps,
163530d68baSNigel Croxon     IN UINTN             Attr
164530d68baSNigel Croxon     );
165530d68baSNigel Croxon 
166530d68baSNigel Croxon //
167530d68baSNigel Croxon //
168530d68baSNigel Croxon //
169530d68baSNigel Croxon 
170530d68baSNigel Croxon INTN EFIAPI
171530d68baSNigel Croxon _SPrint (
172530d68baSNigel Croxon     IN VOID     *Context,
173530d68baSNigel Croxon     IN CHAR16   *Buffer
174530d68baSNigel Croxon     );
175530d68baSNigel Croxon 
176530d68baSNigel Croxon INTN EFIAPI
177530d68baSNigel Croxon _PoolPrint (
178530d68baSNigel Croxon     IN VOID     *Context,
179530d68baSNigel Croxon     IN CHAR16   *Buffer
180530d68baSNigel Croxon     );
181530d68baSNigel Croxon 
182530d68baSNigel Croxon INTN
183530d68baSNigel Croxon DbgPrint (
184530d68baSNigel Croxon     IN INTN      mask,
185530d68baSNigel Croxon     IN CHAR8     *fmt,
186530d68baSNigel Croxon     ...
187530d68baSNigel Croxon     )
188530d68baSNigel Croxon /*++
189530d68baSNigel Croxon 
190530d68baSNigel Croxon Routine Description:
191530d68baSNigel Croxon 
192530d68baSNigel Croxon     Prints a formatted unicode string to the default StandardError console
193530d68baSNigel Croxon 
194530d68baSNigel Croxon Arguments:
195530d68baSNigel Croxon 
196530d68baSNigel Croxon     mask        - Bit mask of debug string.  If a bit is set in the
197530d68baSNigel Croxon                   mask that is also set in EFIDebug the string is
198530d68baSNigel Croxon                   printed; otherwise, the string is not printed
199530d68baSNigel Croxon 
200530d68baSNigel Croxon     fmt         - Format string
201530d68baSNigel Croxon 
202530d68baSNigel Croxon Returns:
203530d68baSNigel Croxon 
204530d68baSNigel Croxon     Length of string printed to the StandardError console
205530d68baSNigel Croxon 
206530d68baSNigel Croxon --*/
207530d68baSNigel Croxon {
208530d68baSNigel Croxon     SIMPLE_TEXT_OUTPUT_INTERFACE    *DbgOut;
209530d68baSNigel Croxon     PRINT_STATE     ps;
210530d68baSNigel Croxon     va_list         args;
211530d68baSNigel Croxon     UINTN           back;
212530d68baSNigel Croxon     UINTN           attr;
213530d68baSNigel Croxon     UINTN           SavedAttribute;
214530d68baSNigel Croxon 
215530d68baSNigel Croxon 
216530d68baSNigel Croxon     if (!(EFIDebug & mask)) {
217530d68baSNigel Croxon         return 0;
218530d68baSNigel Croxon     }
219530d68baSNigel Croxon 
220530d68baSNigel Croxon     va_start (args, fmt);
221530d68baSNigel Croxon     ZeroMem (&ps, sizeof(ps));
222530d68baSNigel Croxon 
223530d68baSNigel Croxon     ps.Output = _DbgOut;
224530d68baSNigel Croxon     ps.fmt.Ascii = TRUE;
225530d68baSNigel Croxon     ps.fmt.pc = fmt;
226530d68baSNigel Croxon     va_copy(ps.args, args);
227530d68baSNigel Croxon     ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED);
228530d68baSNigel Croxon 
229530d68baSNigel Croxon     DbgOut = LibRuntimeDebugOut;
230530d68baSNigel Croxon 
231530d68baSNigel Croxon     if (!DbgOut) {
232530d68baSNigel Croxon         DbgOut = ST->StdErr;
233530d68baSNigel Croxon     }
234530d68baSNigel Croxon 
235530d68baSNigel Croxon     if (DbgOut) {
236530d68baSNigel Croxon         ps.Attr = DbgOut->Mode->Attribute;
237530d68baSNigel Croxon         ps.Context = DbgOut;
23809027207SNigel Croxon         ps.SetAttr = (INTN (EFIAPI *)(VOID *, UINTN))  DbgOut->SetAttribute;
239530d68baSNigel Croxon     }
240530d68baSNigel Croxon 
241530d68baSNigel Croxon     SavedAttribute = ps.Attr;
242530d68baSNigel Croxon 
243530d68baSNigel Croxon     back = (ps.Attr >> 4) & 0xf;
244530d68baSNigel Croxon     ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
245530d68baSNigel Croxon     ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
246530d68baSNigel Croxon     ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
247530d68baSNigel Croxon 
248530d68baSNigel Croxon     attr = ps.AttrNorm;
249530d68baSNigel Croxon 
250530d68baSNigel Croxon     if (mask & D_WARN) {
251530d68baSNigel Croxon         attr = ps.AttrHighlight;
252530d68baSNigel Croxon     }
253530d68baSNigel Croxon 
254530d68baSNigel Croxon     if (mask & D_ERROR) {
255530d68baSNigel Croxon         attr = ps.AttrError;
256530d68baSNigel Croxon     }
257530d68baSNigel Croxon 
258530d68baSNigel Croxon     if (ps.SetAttr) {
259530d68baSNigel Croxon         ps.Attr = attr;
260530d68baSNigel Croxon         uefi_call_wrapper(ps.SetAttr, 2, ps.Context, attr);
261530d68baSNigel Croxon     }
262530d68baSNigel Croxon 
263530d68baSNigel Croxon     _Print (&ps);
264530d68baSNigel Croxon 
265530d68baSNigel Croxon     va_end (ps.args);
266530d68baSNigel Croxon     va_end (args);
267530d68baSNigel Croxon 
268530d68baSNigel Croxon     //
269530d68baSNigel Croxon     // Restore original attributes
270530d68baSNigel Croxon     //
271530d68baSNigel Croxon 
272530d68baSNigel Croxon     if (ps.SetAttr) {
273530d68baSNigel Croxon         uefi_call_wrapper(ps.SetAttr, 2, ps.Context, SavedAttribute);
274530d68baSNigel Croxon     }
275530d68baSNigel Croxon 
276530d68baSNigel Croxon     return 0;
277530d68baSNigel Croxon }
278530d68baSNigel Croxon 
279530d68baSNigel Croxon STATIC
280530d68baSNigel Croxon INTN
281530d68baSNigel Croxon IsLocalPrint(void *func)
282530d68baSNigel Croxon {
283530d68baSNigel Croxon 	if (func == _DbgOut || func == _SPrint || func == _PoolPrint)
284530d68baSNigel Croxon 		return 1;
285530d68baSNigel Croxon 	return 0;
286530d68baSNigel Croxon }
287530d68baSNigel Croxon 
288530d68baSNigel Croxon STATIC
289530d68baSNigel Croxon INTN EFIAPI
290530d68baSNigel Croxon _DbgOut (
291530d68baSNigel Croxon     IN VOID     *Context,
292530d68baSNigel Croxon     IN CHAR16   *Buffer
293530d68baSNigel Croxon     )
294530d68baSNigel Croxon // Append string worker for DbgPrint
295530d68baSNigel Croxon {
296530d68baSNigel Croxon     SIMPLE_TEXT_OUTPUT_INTERFACE    *DbgOut;
297530d68baSNigel Croxon 
298530d68baSNigel Croxon     DbgOut = Context;
299530d68baSNigel Croxon //    if (!DbgOut && ST && ST->ConOut) {
300530d68baSNigel Croxon //        DbgOut = ST->ConOut;
301530d68baSNigel Croxon //    }
302530d68baSNigel Croxon 
303530d68baSNigel Croxon     if (DbgOut) {
304530d68baSNigel Croxon 	if (IsLocalPrint(DbgOut->OutputString))
305530d68baSNigel Croxon 		DbgOut->OutputString(DbgOut, Buffer);
306530d68baSNigel Croxon         else
307530d68baSNigel Croxon 		uefi_call_wrapper(DbgOut->OutputString, 2, DbgOut, Buffer);
308530d68baSNigel Croxon     }
309530d68baSNigel Croxon 
310530d68baSNigel Croxon     return 0;
311530d68baSNigel Croxon }
312530d68baSNigel Croxon 
313530d68baSNigel Croxon INTN EFIAPI
314530d68baSNigel Croxon _SPrint (
315530d68baSNigel Croxon     IN VOID     *Context,
316530d68baSNigel Croxon     IN CHAR16   *Buffer
317530d68baSNigel Croxon     )
318530d68baSNigel Croxon // Append string worker for SPrint, PoolPrint and CatPrint
319530d68baSNigel Croxon {
320530d68baSNigel Croxon     UINTN           len;
321530d68baSNigel Croxon     POOL_PRINT      *spc;
322530d68baSNigel Croxon 
323530d68baSNigel Croxon     spc = Context;
324530d68baSNigel Croxon     len = StrLen(Buffer);
325530d68baSNigel Croxon 
326530d68baSNigel Croxon     //
327530d68baSNigel Croxon     // Is the string is over the max truncate it
328530d68baSNigel Croxon     //
329530d68baSNigel Croxon 
330530d68baSNigel Croxon     if (spc->len + len > spc->maxlen) {
331530d68baSNigel Croxon         len = spc->maxlen - spc->len;
332530d68baSNigel Croxon     }
333530d68baSNigel Croxon 
334530d68baSNigel Croxon     //
335530d68baSNigel Croxon     // Append the new text
336530d68baSNigel Croxon     //
337530d68baSNigel Croxon 
338530d68baSNigel Croxon     CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16));
339530d68baSNigel Croxon     spc->len += len;
340530d68baSNigel Croxon 
341530d68baSNigel Croxon     //
342530d68baSNigel Croxon     // Null terminate it
343530d68baSNigel Croxon     //
344530d68baSNigel Croxon 
345530d68baSNigel Croxon     if (spc->len < spc->maxlen) {
346530d68baSNigel Croxon         spc->str[spc->len] = 0;
347530d68baSNigel Croxon     } else if (spc->maxlen) {
348dada63fdSNigel Croxon         spc->str[spc->maxlen] = 0;
349530d68baSNigel Croxon     }
350530d68baSNigel Croxon 
351530d68baSNigel Croxon     return 0;
352530d68baSNigel Croxon }
353530d68baSNigel Croxon 
354530d68baSNigel Croxon 
355530d68baSNigel Croxon INTN EFIAPI
356530d68baSNigel Croxon _PoolPrint (
357530d68baSNigel Croxon     IN VOID     *Context,
358530d68baSNigel Croxon     IN CHAR16   *Buffer
359530d68baSNigel Croxon     )
360530d68baSNigel Croxon // Append string worker for PoolPrint and CatPrint
361530d68baSNigel Croxon {
362530d68baSNigel Croxon     UINTN           newlen;
363530d68baSNigel Croxon     POOL_PRINT      *spc;
364530d68baSNigel Croxon 
365530d68baSNigel Croxon     spc = Context;
366530d68baSNigel Croxon     newlen = spc->len + StrLen(Buffer) + 1;
367530d68baSNigel Croxon 
368530d68baSNigel Croxon     //
369530d68baSNigel Croxon     // Is the string is over the max, grow the buffer
370530d68baSNigel Croxon     //
371530d68baSNigel Croxon 
372530d68baSNigel Croxon     if (newlen > spc->maxlen) {
373530d68baSNigel Croxon 
374530d68baSNigel Croxon         //
375530d68baSNigel Croxon         // Grow the pool buffer
376530d68baSNigel Croxon         //
377530d68baSNigel Croxon 
378530d68baSNigel Croxon         newlen += PRINT_STRING_LEN;
379530d68baSNigel Croxon         spc->maxlen = newlen;
380530d68baSNigel Croxon         spc->str = ReallocatePool (
381530d68baSNigel Croxon                         spc->str,
382530d68baSNigel Croxon                         spc->len * sizeof(CHAR16),
383530d68baSNigel Croxon                         spc->maxlen * sizeof(CHAR16)
384530d68baSNigel Croxon                         );
385530d68baSNigel Croxon 
386530d68baSNigel Croxon         if (!spc->str) {
387530d68baSNigel Croxon             spc->len = 0;
388530d68baSNigel Croxon             spc->maxlen = 0;
389530d68baSNigel Croxon         }
390530d68baSNigel Croxon     }
391530d68baSNigel Croxon 
392530d68baSNigel Croxon     //
393530d68baSNigel Croxon     // Append the new text
394530d68baSNigel Croxon     //
395530d68baSNigel Croxon 
396530d68baSNigel Croxon     return _SPrint (Context, Buffer);
397530d68baSNigel Croxon }
398530d68baSNigel Croxon 
399530d68baSNigel Croxon 
400530d68baSNigel Croxon 
401530d68baSNigel Croxon VOID
402530d68baSNigel Croxon _PoolCatPrint (
403530d68baSNigel Croxon     IN CHAR16           *fmt,
404530d68baSNigel Croxon     IN va_list          args,
405530d68baSNigel Croxon     IN OUT POOL_PRINT   *spc,
40609027207SNigel Croxon     IN INTN             (EFIAPI *Output)(VOID *context, CHAR16 *str)
407530d68baSNigel Croxon     )
408530d68baSNigel Croxon // Dispath function for SPrint, PoolPrint, and CatPrint
409530d68baSNigel Croxon {
410530d68baSNigel Croxon     PRINT_STATE         ps;
411530d68baSNigel Croxon 
412530d68baSNigel Croxon     ZeroMem (&ps, sizeof(ps));
413530d68baSNigel Croxon     ps.Output  = Output;
414530d68baSNigel Croxon     ps.Context = spc;
415530d68baSNigel Croxon     ps.fmt.pw = fmt;
416530d68baSNigel Croxon     va_copy(ps.args, args);
417530d68baSNigel Croxon     _Print (&ps);
418530d68baSNigel Croxon     va_end(ps.args);
419530d68baSNigel Croxon }
420530d68baSNigel Croxon 
421530d68baSNigel Croxon 
422530d68baSNigel Croxon 
423530d68baSNigel Croxon UINTN
424530d68baSNigel Croxon VSPrint (
425530d68baSNigel Croxon     OUT CHAR16  *Str,
426530d68baSNigel Croxon     IN UINTN    StrSize,
427530d68baSNigel Croxon     IN CHAR16   *fmt,
428530d68baSNigel Croxon     va_list     args
429530d68baSNigel Croxon     )
430530d68baSNigel Croxon /*++
431530d68baSNigel Croxon 
432530d68baSNigel Croxon Routine Description:
433530d68baSNigel Croxon 
434530d68baSNigel Croxon     Prints a formatted unicode string to a buffer using a va_list
435530d68baSNigel Croxon 
436530d68baSNigel Croxon Arguments:
437530d68baSNigel Croxon 
438530d68baSNigel Croxon     Str         - Output buffer to print the formatted string into
439530d68baSNigel Croxon 
440530d68baSNigel Croxon     StrSize     - Size of Str.  String is truncated to this size.
441530d68baSNigel Croxon                   A size of 0 means there is no limit
442530d68baSNigel Croxon 
443530d68baSNigel Croxon     fmt         - The format string
444530d68baSNigel Croxon 
445530d68baSNigel Croxon     args        - va_list
446530d68baSNigel Croxon 
447530d68baSNigel Croxon 
448530d68baSNigel Croxon Returns:
449530d68baSNigel Croxon 
450530d68baSNigel Croxon     String length returned in buffer
451530d68baSNigel Croxon 
452530d68baSNigel Croxon --*/
453530d68baSNigel Croxon {
454530d68baSNigel Croxon     POOL_PRINT          spc;
455530d68baSNigel Croxon 
456530d68baSNigel Croxon     spc.str    = Str;
457530d68baSNigel Croxon     spc.maxlen = StrSize / sizeof(CHAR16) - 1;
458530d68baSNigel Croxon     spc.len    = 0;
459530d68baSNigel Croxon 
460530d68baSNigel Croxon     _PoolCatPrint (fmt, args, &spc, _SPrint);
461530d68baSNigel Croxon 
462530d68baSNigel Croxon     return spc.len;
463530d68baSNigel Croxon }
464530d68baSNigel Croxon 
465530d68baSNigel Croxon UINTN
466530d68baSNigel Croxon SPrint (
467530d68baSNigel Croxon     OUT CHAR16  *Str,
468530d68baSNigel Croxon     IN UINTN    StrSize,
469530d68baSNigel Croxon     IN CHAR16   *fmt,
470530d68baSNigel Croxon     ...
471530d68baSNigel Croxon     )
472530d68baSNigel Croxon /*++
473530d68baSNigel Croxon 
474530d68baSNigel Croxon Routine Description:
475530d68baSNigel Croxon 
476530d68baSNigel Croxon     Prints a formatted unicode string to a buffer
477530d68baSNigel Croxon 
478530d68baSNigel Croxon Arguments:
479530d68baSNigel Croxon 
480530d68baSNigel Croxon     Str         - Output buffer to print the formatted string into
481530d68baSNigel Croxon 
482530d68baSNigel Croxon     StrSize     - Size of Str.  String is truncated to this size.
483530d68baSNigel Croxon                   A size of 0 means there is no limit
484530d68baSNigel Croxon 
485530d68baSNigel Croxon     fmt         - The format string
486530d68baSNigel Croxon 
487530d68baSNigel Croxon Returns:
488530d68baSNigel Croxon 
489530d68baSNigel Croxon     String length returned in buffer
490530d68baSNigel Croxon 
491530d68baSNigel Croxon --*/
492530d68baSNigel Croxon {
493530d68baSNigel Croxon     va_list          args;
494530d68baSNigel Croxon     UINTN            len;
495530d68baSNigel Croxon 
496530d68baSNigel Croxon     va_start (args, fmt);
497530d68baSNigel Croxon     len = VSPrint(Str, StrSize, fmt, args);
498530d68baSNigel Croxon     va_end (args);
499530d68baSNigel Croxon 
500530d68baSNigel Croxon     return len;
501530d68baSNigel Croxon }
502530d68baSNigel Croxon 
503530d68baSNigel Croxon CHAR16 *
504530d68baSNigel Croxon VPoolPrint (
505530d68baSNigel Croxon     IN CHAR16           *fmt,
506530d68baSNigel Croxon     va_list             args
507530d68baSNigel Croxon     )
508530d68baSNigel Croxon /*++
509530d68baSNigel Croxon 
510530d68baSNigel Croxon Routine Description:
511530d68baSNigel Croxon 
512530d68baSNigel Croxon     Prints a formatted unicode string to allocated pool using va_list argument.
513530d68baSNigel Croxon     The caller must free the resulting buffer.
514530d68baSNigel Croxon 
515530d68baSNigel Croxon Arguments:
516530d68baSNigel Croxon 
517530d68baSNigel Croxon     fmt         - The format string
518530d68baSNigel Croxon     args        - The arguments in va_list form
519530d68baSNigel Croxon 
520530d68baSNigel Croxon Returns:
521530d68baSNigel Croxon 
522530d68baSNigel Croxon     Allocated buffer with the formatted string printed in it.
523530d68baSNigel Croxon     The caller must free the allocated buffer.   The buffer
524530d68baSNigel Croxon     allocation is not packed.
525530d68baSNigel Croxon 
526530d68baSNigel Croxon --*/
527530d68baSNigel Croxon {
528530d68baSNigel Croxon     POOL_PRINT          spc;
529530d68baSNigel Croxon     ZeroMem (&spc, sizeof(spc));
530530d68baSNigel Croxon     _PoolCatPrint (fmt, args, &spc, _PoolPrint);
531530d68baSNigel Croxon     return spc.str;
532530d68baSNigel Croxon }
533530d68baSNigel Croxon 
534530d68baSNigel Croxon CHAR16 *
535530d68baSNigel Croxon PoolPrint (
536530d68baSNigel Croxon     IN CHAR16           *fmt,
537530d68baSNigel Croxon     ...
538530d68baSNigel Croxon     )
539530d68baSNigel Croxon /*++
540530d68baSNigel Croxon 
541530d68baSNigel Croxon Routine Description:
542530d68baSNigel Croxon 
543530d68baSNigel Croxon     Prints a formatted unicode string to allocated pool.  The caller
544530d68baSNigel Croxon     must free the resulting buffer.
545530d68baSNigel Croxon 
546530d68baSNigel Croxon Arguments:
547530d68baSNigel Croxon 
548530d68baSNigel Croxon     fmt         - The format string
549530d68baSNigel Croxon 
550530d68baSNigel Croxon Returns:
551530d68baSNigel Croxon 
552530d68baSNigel Croxon     Allocated buffer with the formatted string printed in it.
553530d68baSNigel Croxon     The caller must free the allocated buffer.   The buffer
554530d68baSNigel Croxon     allocation is not packed.
555530d68baSNigel Croxon 
556530d68baSNigel Croxon --*/
557530d68baSNigel Croxon {
558530d68baSNigel Croxon     va_list args;
559530d68baSNigel Croxon     CHAR16 *pool;
560530d68baSNigel Croxon     va_start (args, fmt);
561530d68baSNigel Croxon     pool = VPoolPrint(fmt, args);
562530d68baSNigel Croxon     va_end (args);
563530d68baSNigel Croxon     return pool;
564530d68baSNigel Croxon }
565530d68baSNigel Croxon 
566530d68baSNigel Croxon CHAR16 *
567530d68baSNigel Croxon CatPrint (
568530d68baSNigel Croxon     IN OUT POOL_PRINT   *Str,
569530d68baSNigel Croxon     IN CHAR16           *fmt,
570530d68baSNigel Croxon     ...
571530d68baSNigel Croxon     )
572530d68baSNigel Croxon /*++
573530d68baSNigel Croxon 
574530d68baSNigel Croxon Routine Description:
575530d68baSNigel Croxon 
576530d68baSNigel Croxon     Concatenates a formatted unicode string to allocated pool.
577530d68baSNigel Croxon     The caller must free the resulting buffer.
578530d68baSNigel Croxon 
579530d68baSNigel Croxon Arguments:
580530d68baSNigel Croxon 
581530d68baSNigel Croxon     Str         - Tracks the allocated pool, size in use, and
582530d68baSNigel Croxon                   amount of pool allocated.
583530d68baSNigel Croxon 
584530d68baSNigel Croxon     fmt         - The format string
585530d68baSNigel Croxon 
586530d68baSNigel Croxon Returns:
587530d68baSNigel Croxon 
588530d68baSNigel Croxon     Allocated buffer with the formatted string printed in it.
589530d68baSNigel Croxon     The caller must free the allocated buffer.   The buffer
590530d68baSNigel Croxon     allocation is not packed.
591530d68baSNigel Croxon 
592530d68baSNigel Croxon --*/
593530d68baSNigel Croxon {
594530d68baSNigel Croxon     va_list             args;
595530d68baSNigel Croxon 
596530d68baSNigel Croxon     va_start (args, fmt);
597530d68baSNigel Croxon     _PoolCatPrint (fmt, args, Str, _PoolPrint);
598530d68baSNigel Croxon     va_end (args);
599530d68baSNigel Croxon     return Str->str;
600530d68baSNigel Croxon }
601530d68baSNigel Croxon 
602530d68baSNigel Croxon 
603530d68baSNigel Croxon 
604530d68baSNigel Croxon UINTN
605530d68baSNigel Croxon Print (
606530d68baSNigel Croxon     IN CHAR16   *fmt,
607530d68baSNigel Croxon     ...
608530d68baSNigel Croxon     )
609530d68baSNigel Croxon /*++
610530d68baSNigel Croxon 
611530d68baSNigel Croxon Routine Description:
612530d68baSNigel Croxon 
613530d68baSNigel Croxon     Prints a formatted unicode string to the default console
614530d68baSNigel Croxon 
615530d68baSNigel Croxon Arguments:
616530d68baSNigel Croxon 
617530d68baSNigel Croxon     fmt         - Format string
618530d68baSNigel Croxon 
619530d68baSNigel Croxon Returns:
620530d68baSNigel Croxon 
621530d68baSNigel Croxon     Length of string printed to the console
622530d68baSNigel Croxon 
623530d68baSNigel Croxon --*/
624530d68baSNigel Croxon {
625530d68baSNigel Croxon     va_list     args;
626530d68baSNigel Croxon     UINTN       back;
627530d68baSNigel Croxon 
628530d68baSNigel Croxon     va_start (args, fmt);
629530d68baSNigel Croxon     back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
630530d68baSNigel Croxon     va_end (args);
631530d68baSNigel Croxon     return back;
632530d68baSNigel Croxon }
633530d68baSNigel Croxon 
634530d68baSNigel Croxon UINTN
635530d68baSNigel Croxon VPrint (
636530d68baSNigel Croxon     IN CHAR16   *fmt,
637530d68baSNigel Croxon     va_list     args
638530d68baSNigel Croxon     )
639530d68baSNigel Croxon /*++
640530d68baSNigel Croxon 
641530d68baSNigel Croxon Routine Description:
642530d68baSNigel Croxon 
643530d68baSNigel Croxon     Prints a formatted unicode string to the default console using a va_list
644530d68baSNigel Croxon 
645530d68baSNigel Croxon Arguments:
646530d68baSNigel Croxon 
647530d68baSNigel Croxon     fmt         - Format string
648530d68baSNigel Croxon     args        - va_list
649530d68baSNigel Croxon Returns:
650530d68baSNigel Croxon 
651530d68baSNigel Croxon     Length of string printed to the console
652530d68baSNigel Croxon 
653530d68baSNigel Croxon --*/
654530d68baSNigel Croxon {
655530d68baSNigel Croxon     return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
656530d68baSNigel Croxon }
657530d68baSNigel Croxon 
658530d68baSNigel Croxon 
659530d68baSNigel Croxon UINTN
660530d68baSNigel Croxon PrintAt (
661530d68baSNigel Croxon     IN UINTN     Column,
662530d68baSNigel Croxon     IN UINTN     Row,
663530d68baSNigel Croxon     IN CHAR16    *fmt,
664530d68baSNigel Croxon     ...
665530d68baSNigel Croxon     )
666530d68baSNigel Croxon /*++
667530d68baSNigel Croxon 
668530d68baSNigel Croxon Routine Description:
669530d68baSNigel Croxon 
670530d68baSNigel Croxon     Prints a formatted unicode string to the default console, at
671530d68baSNigel Croxon     the supplied cursor position
672530d68baSNigel Croxon 
673530d68baSNigel Croxon Arguments:
674530d68baSNigel Croxon 
675530d68baSNigel Croxon     Column, Row - The cursor position to print the string at
676530d68baSNigel Croxon 
677530d68baSNigel Croxon     fmt         - Format string
678530d68baSNigel Croxon 
679530d68baSNigel Croxon Returns:
680530d68baSNigel Croxon 
681530d68baSNigel Croxon     Length of string printed to the console
682530d68baSNigel Croxon 
683530d68baSNigel Croxon --*/
684530d68baSNigel Croxon {
685530d68baSNigel Croxon     va_list     args;
686530d68baSNigel Croxon     UINTN       back;
687530d68baSNigel Croxon 
688530d68baSNigel Croxon     va_start (args, fmt);
689530d68baSNigel Croxon     back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
690530d68baSNigel Croxon     va_end (args);
691530d68baSNigel Croxon     return back;
692530d68baSNigel Croxon }
693530d68baSNigel Croxon 
694530d68baSNigel Croxon 
695530d68baSNigel Croxon UINTN
696530d68baSNigel Croxon IPrint (
697530d68baSNigel Croxon     IN SIMPLE_TEXT_OUTPUT_INTERFACE    *Out,
698530d68baSNigel Croxon     IN CHAR16                          *fmt,
699530d68baSNigel Croxon     ...
700530d68baSNigel Croxon     )
701530d68baSNigel Croxon /*++
702530d68baSNigel Croxon 
703530d68baSNigel Croxon Routine Description:
704530d68baSNigel Croxon 
705530d68baSNigel Croxon     Prints a formatted unicode string to the specified console
706530d68baSNigel Croxon 
707530d68baSNigel Croxon Arguments:
708530d68baSNigel Croxon 
709530d68baSNigel Croxon     Out         - The console to print the string too
710530d68baSNigel Croxon 
711530d68baSNigel Croxon     fmt         - Format string
712530d68baSNigel Croxon 
713530d68baSNigel Croxon Returns:
714530d68baSNigel Croxon 
715530d68baSNigel Croxon     Length of string printed to the console
716530d68baSNigel Croxon 
717530d68baSNigel Croxon --*/
718530d68baSNigel Croxon {
719530d68baSNigel Croxon     va_list     args;
720530d68baSNigel Croxon     UINTN       back;
721530d68baSNigel Croxon 
722530d68baSNigel Croxon     va_start (args, fmt);
723530d68baSNigel Croxon     back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
724530d68baSNigel Croxon     va_end (args);
725530d68baSNigel Croxon     return back;
726530d68baSNigel Croxon }
727530d68baSNigel Croxon 
728530d68baSNigel Croxon 
729530d68baSNigel Croxon UINTN
730530d68baSNigel Croxon IPrintAt (
731530d68baSNigel Croxon     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
732530d68baSNigel Croxon     IN UINTN                            Column,
733530d68baSNigel Croxon     IN UINTN                            Row,
734530d68baSNigel Croxon     IN CHAR16                           *fmt,
735530d68baSNigel Croxon     ...
736530d68baSNigel Croxon     )
737530d68baSNigel Croxon /*++
738530d68baSNigel Croxon 
739530d68baSNigel Croxon Routine Description:
740530d68baSNigel Croxon 
741530d68baSNigel Croxon     Prints a formatted unicode string to the specified console, at
742530d68baSNigel Croxon     the supplied cursor position
743530d68baSNigel Croxon 
744530d68baSNigel Croxon Arguments:
745530d68baSNigel Croxon 
746ab6c6ef7SNigel Croxon     Out         - The console to print the string to
747530d68baSNigel Croxon 
748530d68baSNigel Croxon     Column, Row - The cursor position to print the string at
749530d68baSNigel Croxon 
750530d68baSNigel Croxon     fmt         - Format string
751530d68baSNigel Croxon 
752530d68baSNigel Croxon Returns:
753530d68baSNigel Croxon 
754530d68baSNigel Croxon     Length of string printed to the console
755530d68baSNigel Croxon 
756530d68baSNigel Croxon --*/
757530d68baSNigel Croxon {
758530d68baSNigel Croxon     va_list     args;
759530d68baSNigel Croxon     UINTN       back;
760530d68baSNigel Croxon 
761530d68baSNigel Croxon     va_start (args, fmt);
762ab6c6ef7SNigel Croxon     back = _IPrint (Column, Row, Out, fmt, NULL, args);
763530d68baSNigel Croxon     va_end (args);
764530d68baSNigel Croxon     return back;
765530d68baSNigel Croxon }
766530d68baSNigel Croxon 
767530d68baSNigel Croxon 
768530d68baSNigel Croxon UINTN
769530d68baSNigel Croxon _IPrint (
770530d68baSNigel Croxon     IN UINTN                            Column,
771530d68baSNigel Croxon     IN UINTN                            Row,
772530d68baSNigel Croxon     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
773530d68baSNigel Croxon     IN CHAR16                           *fmt,
774530d68baSNigel Croxon     IN CHAR8                            *fmta,
775530d68baSNigel Croxon     IN va_list                          args
776530d68baSNigel Croxon     )
777530d68baSNigel Croxon // Display string worker for: Print, PrintAt, IPrint, IPrintAt
778530d68baSNigel Croxon {
779530d68baSNigel Croxon     PRINT_STATE     ps;
780530d68baSNigel Croxon     UINTN            back;
781530d68baSNigel Croxon 
782530d68baSNigel Croxon     ZeroMem (&ps, sizeof(ps));
783530d68baSNigel Croxon     ps.Context = Out;
78409027207SNigel Croxon     ps.Output  = (INTN (EFIAPI *)(VOID *, CHAR16 *)) Out->OutputString;
78509027207SNigel Croxon     ps.SetAttr = (INTN (EFIAPI *)(VOID *, UINTN))  Out->SetAttribute;
786530d68baSNigel Croxon     ps.Attr = Out->Mode->Attribute;
787530d68baSNigel Croxon 
788530d68baSNigel Croxon     back = (ps.Attr >> 4) & 0xF;
789530d68baSNigel Croxon     ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
790530d68baSNigel Croxon     ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
791530d68baSNigel Croxon     ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
792530d68baSNigel Croxon 
793530d68baSNigel Croxon     if (fmt) {
794530d68baSNigel Croxon         ps.fmt.pw = fmt;
795530d68baSNigel Croxon     } else {
796530d68baSNigel Croxon         ps.fmt.Ascii = TRUE;
797530d68baSNigel Croxon         ps.fmt.pc = fmta;
798530d68baSNigel Croxon     }
799530d68baSNigel Croxon 
800530d68baSNigel Croxon     va_copy(ps.args, args);
801530d68baSNigel Croxon 
802530d68baSNigel Croxon     if (Column != (UINTN) -1) {
803530d68baSNigel Croxon         uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row);
804530d68baSNigel Croxon     }
805530d68baSNigel Croxon 
806530d68baSNigel Croxon     back = _Print (&ps);
807530d68baSNigel Croxon     va_end(ps.args);
808530d68baSNigel Croxon     return back;
809530d68baSNigel Croxon }
810530d68baSNigel Croxon 
811530d68baSNigel Croxon 
812530d68baSNigel Croxon UINTN
813530d68baSNigel Croxon APrint (
814530d68baSNigel Croxon     IN CHAR8    *fmt,
815530d68baSNigel Croxon     ...
816530d68baSNigel Croxon     )
817530d68baSNigel Croxon /*++
818530d68baSNigel Croxon 
819530d68baSNigel Croxon Routine Description:
820530d68baSNigel Croxon 
821530d68baSNigel Croxon     For those whom really can't deal with unicode, a print
822530d68baSNigel Croxon     function that takes an ascii format string
823530d68baSNigel Croxon 
824530d68baSNigel Croxon Arguments:
825530d68baSNigel Croxon 
826530d68baSNigel Croxon     fmt         - ascii format string
827530d68baSNigel Croxon 
828530d68baSNigel Croxon Returns:
829530d68baSNigel Croxon 
830530d68baSNigel Croxon     Length of string printed to the console
831530d68baSNigel Croxon 
832530d68baSNigel Croxon --*/
833530d68baSNigel Croxon 
834530d68baSNigel Croxon {
835530d68baSNigel Croxon     va_list     args;
836530d68baSNigel Croxon     UINTN       back;
837530d68baSNigel Croxon 
838530d68baSNigel Croxon     va_start (args, fmt);
839530d68baSNigel Croxon     back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
840530d68baSNigel Croxon     va_end (args);
841530d68baSNigel Croxon     return back;
842530d68baSNigel Croxon }
843530d68baSNigel Croxon 
844530d68baSNigel Croxon 
845530d68baSNigel Croxon STATIC
846530d68baSNigel Croxon VOID
847530d68baSNigel Croxon PFLUSH (
848530d68baSNigel Croxon     IN OUT PRINT_STATE     *ps
849530d68baSNigel Croxon     )
850530d68baSNigel Croxon {
851530d68baSNigel Croxon     *ps->Pos = 0;
852530d68baSNigel Croxon     if (IsLocalPrint(ps->Output))
853530d68baSNigel Croxon 	ps->Output(ps->Context, ps->Buffer);
854530d68baSNigel Croxon     else
855530d68baSNigel Croxon     	uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
856530d68baSNigel Croxon     ps->Pos = ps->Buffer;
857530d68baSNigel Croxon }
858530d68baSNigel Croxon 
859530d68baSNigel Croxon STATIC
860530d68baSNigel Croxon VOID
861530d68baSNigel Croxon PSETATTR (
862530d68baSNigel Croxon     IN OUT PRINT_STATE  *ps,
863530d68baSNigel Croxon     IN UINTN             Attr
864530d68baSNigel Croxon     )
865530d68baSNigel Croxon {
866530d68baSNigel Croxon    PFLUSH (ps);
867530d68baSNigel Croxon 
868530d68baSNigel Croxon    ps->RestoreAttr = ps->Attr;
869530d68baSNigel Croxon    if (ps->SetAttr) {
870530d68baSNigel Croxon 	uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
871530d68baSNigel Croxon    }
872530d68baSNigel Croxon 
873530d68baSNigel Croxon    ps->Attr = Attr;
874530d68baSNigel Croxon }
875530d68baSNigel Croxon 
876530d68baSNigel Croxon STATIC
877530d68baSNigel Croxon VOID
878530d68baSNigel Croxon PPUTC (
879530d68baSNigel Croxon     IN OUT PRINT_STATE     *ps,
880530d68baSNigel Croxon     IN CHAR16              c
881530d68baSNigel Croxon     )
882530d68baSNigel Croxon {
883530d68baSNigel Croxon     // if this is a newline, add a carraige return
884530d68baSNigel Croxon     if (c == '\n') {
885530d68baSNigel Croxon         PPUTC (ps, '\r');
886530d68baSNigel Croxon     }
887530d68baSNigel Croxon 
888530d68baSNigel Croxon     *ps->Pos = c;
889530d68baSNigel Croxon     ps->Pos += 1;
890530d68baSNigel Croxon     ps->Len += 1;
891530d68baSNigel Croxon 
892530d68baSNigel Croxon     // if at the end of the buffer, flush it
893530d68baSNigel Croxon     if (ps->Pos >= ps->End) {
894530d68baSNigel Croxon         PFLUSH(ps);
895530d68baSNigel Croxon     }
896530d68baSNigel Croxon }
897530d68baSNigel Croxon 
898530d68baSNigel Croxon 
899530d68baSNigel Croxon STATIC
900530d68baSNigel Croxon CHAR16
901530d68baSNigel Croxon PGETC (
902530d68baSNigel Croxon     IN POINTER      *p
903530d68baSNigel Croxon     )
904530d68baSNigel Croxon {
905530d68baSNigel Croxon     CHAR16      c;
906530d68baSNigel Croxon 
907530d68baSNigel Croxon     c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
908530d68baSNigel Croxon     p->Index += 1;
909530d68baSNigel Croxon 
910530d68baSNigel Croxon     return  c;
911530d68baSNigel Croxon }
912530d68baSNigel Croxon 
913530d68baSNigel Croxon 
914530d68baSNigel Croxon STATIC
915530d68baSNigel Croxon VOID
916530d68baSNigel Croxon PITEM (
917530d68baSNigel Croxon     IN OUT PRINT_STATE  *ps
918530d68baSNigel Croxon     )
919530d68baSNigel Croxon {
920530d68baSNigel Croxon     UINTN               Len, i;
921530d68baSNigel Croxon     PRINT_ITEM          *Item;
922530d68baSNigel Croxon     CHAR16              c;
923530d68baSNigel Croxon 
924530d68baSNigel Croxon     // Get the length of the item
925530d68baSNigel Croxon     Item = ps->Item;
926530d68baSNigel Croxon     Item->Item.Index = 0;
927530d68baSNigel Croxon     while (Item->Item.Index < Item->FieldWidth) {
928530d68baSNigel Croxon         c = PGETC(&Item->Item);
929530d68baSNigel Croxon         if (!c) {
930530d68baSNigel Croxon             Item->Item.Index -= 1;
931530d68baSNigel Croxon             break;
932530d68baSNigel Croxon         }
933530d68baSNigel Croxon     }
934530d68baSNigel Croxon     Len = Item->Item.Index;
935530d68baSNigel Croxon 
936530d68baSNigel Croxon     // if there is no item field width, use the items width
937530d68baSNigel Croxon     if (Item->FieldWidth == (UINTN) -1) {
938530d68baSNigel Croxon         Item->FieldWidth = Len;
939530d68baSNigel Croxon     }
940530d68baSNigel Croxon 
941530d68baSNigel Croxon     // if item is larger then width, update width
942530d68baSNigel Croxon     if (Len > Item->Width) {
943530d68baSNigel Croxon         Item->Width = Len;
944530d68baSNigel Croxon     }
945530d68baSNigel Croxon 
946530d68baSNigel Croxon 
947530d68baSNigel Croxon     // if pad field before, add pad char
948530d68baSNigel Croxon     if (Item->PadBefore) {
949530d68baSNigel Croxon         for (i=Item->Width; i < Item->FieldWidth; i+=1) {
950530d68baSNigel Croxon             PPUTC (ps, ' ');
951530d68baSNigel Croxon         }
952530d68baSNigel Croxon     }
953530d68baSNigel Croxon 
954530d68baSNigel Croxon     // pad item
955530d68baSNigel Croxon     for (i=Len; i < Item->Width; i++) {
956530d68baSNigel Croxon         PPUTC (ps, Item->Pad);
957530d68baSNigel Croxon     }
958530d68baSNigel Croxon 
959530d68baSNigel Croxon     // add the item
960530d68baSNigel Croxon     Item->Item.Index=0;
961530d68baSNigel Croxon     while (Item->Item.Index < Len) {
962530d68baSNigel Croxon         PPUTC (ps, PGETC(&Item->Item));
963530d68baSNigel Croxon     }
964530d68baSNigel Croxon 
965530d68baSNigel Croxon     // If pad at the end, add pad char
966530d68baSNigel Croxon     if (!Item->PadBefore) {
967530d68baSNigel Croxon         for (i=Item->Width; i < Item->FieldWidth; i+=1) {
968530d68baSNigel Croxon             PPUTC (ps, ' ');
969530d68baSNigel Croxon         }
970530d68baSNigel Croxon     }
971530d68baSNigel Croxon }
972530d68baSNigel Croxon 
973530d68baSNigel Croxon 
974530d68baSNigel Croxon STATIC
975530d68baSNigel Croxon UINTN
976530d68baSNigel Croxon _Print (
977530d68baSNigel Croxon     IN PRINT_STATE     *ps
978530d68baSNigel Croxon     )
979530d68baSNigel Croxon /*++
980530d68baSNigel Croxon 
981530d68baSNigel Croxon Routine Description:
982530d68baSNigel Croxon 
983530d68baSNigel Croxon     %w.lF   -   w = width
984530d68baSNigel Croxon                 l = field width
985530d68baSNigel Croxon                 F = format of arg
986530d68baSNigel Croxon 
987530d68baSNigel Croxon   Args F:
988530d68baSNigel Croxon     0       -   pad with zeros
989530d68baSNigel Croxon     -       -   justify on left (default is on right)
990530d68baSNigel Croxon     ,       -   add comma's to field
991530d68baSNigel Croxon     *       -   width provided on stack
992530d68baSNigel Croxon     n       -   Set output attribute to normal (for this field only)
993530d68baSNigel Croxon     h       -   Set output attribute to highlight (for this field only)
994530d68baSNigel Croxon     e       -   Set output attribute to error (for this field only)
995530d68baSNigel Croxon     l       -   Value is 64 bits
996530d68baSNigel Croxon 
997530d68baSNigel Croxon     a       -   ascii string
998530d68baSNigel Croxon     s       -   unicode string
999530d68baSNigel Croxon     X       -   fixed 8 byte value in hex
1000530d68baSNigel Croxon     x       -   hex value
1001*1acb1d9dSNigel Croxon     d       -   value as signed decimal
1002*1acb1d9dSNigel Croxon     u       -   value as unsigned decimal
1003530d68baSNigel Croxon     c       -   Unicode char
1004530d68baSNigel Croxon     t       -   EFI time structure
1005530d68baSNigel Croxon     g       -   Pointer to GUID
1006530d68baSNigel Croxon     r       -   EFI status code (result code)
1007530d68baSNigel Croxon 
1008530d68baSNigel Croxon     N       -   Set output attribute to normal
1009530d68baSNigel Croxon     H       -   Set output attribute to highlight
1010530d68baSNigel Croxon     E       -   Set output attribute to error
1011530d68baSNigel Croxon     %       -   Print a %
1012530d68baSNigel Croxon 
1013530d68baSNigel Croxon Arguments:
1014530d68baSNigel Croxon 
1015530d68baSNigel Croxon     SystemTable     - The system table
1016530d68baSNigel Croxon 
1017530d68baSNigel Croxon Returns:
1018530d68baSNigel Croxon 
1019530d68baSNigel Croxon     Number of charactors written
1020530d68baSNigel Croxon 
1021530d68baSNigel Croxon --*/
1022530d68baSNigel Croxon {
1023530d68baSNigel Croxon     CHAR16          c;
1024530d68baSNigel Croxon     UINTN           Attr;
1025530d68baSNigel Croxon     PRINT_ITEM      Item;
1026530d68baSNigel Croxon     CHAR16          Buffer[PRINT_STRING_LEN];
1027530d68baSNigel Croxon 
1028530d68baSNigel Croxon     ps->Len = 0;
1029530d68baSNigel Croxon     ps->Buffer = Buffer;
1030530d68baSNigel Croxon     ps->Pos = Buffer;
1031530d68baSNigel Croxon     ps->End = Buffer + PRINT_STRING_LEN - 1;
1032530d68baSNigel Croxon     ps->Item = &Item;
1033530d68baSNigel Croxon 
1034530d68baSNigel Croxon     ps->fmt.Index = 0;
1035530d68baSNigel Croxon     while ((c = PGETC(&ps->fmt))) {
1036530d68baSNigel Croxon 
1037530d68baSNigel Croxon         if (c != '%') {
1038530d68baSNigel Croxon             PPUTC ( ps, c );
1039530d68baSNigel Croxon             continue;
1040530d68baSNigel Croxon         }
1041530d68baSNigel Croxon 
1042530d68baSNigel Croxon         // setup for new item
1043530d68baSNigel Croxon         Item.FieldWidth = (UINTN) -1;
1044530d68baSNigel Croxon         Item.Width = 0;
1045530d68baSNigel Croxon         Item.WidthParse = &Item.Width;
1046530d68baSNigel Croxon         Item.Pad = ' ';
1047530d68baSNigel Croxon         Item.PadBefore = TRUE;
1048530d68baSNigel Croxon         Item.Comma = FALSE;
1049530d68baSNigel Croxon         Item.Long = FALSE;
1050530d68baSNigel Croxon         Item.Item.Ascii = FALSE;
1051530d68baSNigel Croxon         Item.Item.pw = NULL;
1052530d68baSNigel Croxon         ps->RestoreAttr = 0;
1053530d68baSNigel Croxon         Attr = 0;
1054530d68baSNigel Croxon 
1055530d68baSNigel Croxon         while ((c = PGETC(&ps->fmt))) {
1056530d68baSNigel Croxon 
1057530d68baSNigel Croxon             switch (c) {
1058530d68baSNigel Croxon 
1059530d68baSNigel Croxon             case '%':
1060530d68baSNigel Croxon                 //
1061530d68baSNigel Croxon                 // %% -> %
1062530d68baSNigel Croxon                 //
1063530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1064530d68baSNigel Croxon                 Item.Item.pw[0] = '%';
1065530d68baSNigel Croxon                 Item.Item.pw[1] = 0;
1066530d68baSNigel Croxon                 break;
1067530d68baSNigel Croxon 
1068530d68baSNigel Croxon             case '0':
1069530d68baSNigel Croxon                 Item.Pad = '0';
1070530d68baSNigel Croxon                 break;
1071530d68baSNigel Croxon 
1072530d68baSNigel Croxon             case '-':
1073530d68baSNigel Croxon                 Item.PadBefore = FALSE;
1074530d68baSNigel Croxon                 break;
1075530d68baSNigel Croxon 
1076530d68baSNigel Croxon             case ',':
1077530d68baSNigel Croxon                 Item.Comma = TRUE;
1078530d68baSNigel Croxon                 break;
1079530d68baSNigel Croxon 
1080530d68baSNigel Croxon             case '.':
1081530d68baSNigel Croxon                 Item.WidthParse = &Item.FieldWidth;
1082530d68baSNigel Croxon                 break;
1083530d68baSNigel Croxon 
1084530d68baSNigel Croxon             case '*':
1085530d68baSNigel Croxon                 *Item.WidthParse = va_arg(ps->args, UINTN);
1086530d68baSNigel Croxon                 break;
1087530d68baSNigel Croxon 
1088530d68baSNigel Croxon             case '1':
1089530d68baSNigel Croxon             case '2':
1090530d68baSNigel Croxon             case '3':
1091530d68baSNigel Croxon             case '4':
1092530d68baSNigel Croxon             case '5':
1093530d68baSNigel Croxon             case '6':
1094530d68baSNigel Croxon             case '7':
1095530d68baSNigel Croxon             case '8':
1096530d68baSNigel Croxon             case '9':
1097530d68baSNigel Croxon                 *Item.WidthParse = 0;
1098530d68baSNigel Croxon                 do {
1099530d68baSNigel Croxon                     *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
1100530d68baSNigel Croxon                     c = PGETC(&ps->fmt);
1101530d68baSNigel Croxon                 } while (c >= '0'  &&  c <= '9') ;
1102530d68baSNigel Croxon                 ps->fmt.Index -= 1;
1103530d68baSNigel Croxon                 break;
1104530d68baSNigel Croxon 
1105530d68baSNigel Croxon             case 'a':
1106530d68baSNigel Croxon                 Item.Item.pc = va_arg(ps->args, CHAR8 *);
1107530d68baSNigel Croxon                 Item.Item.Ascii = TRUE;
1108530d68baSNigel Croxon                 if (!Item.Item.pc) {
1109530d68baSNigel Croxon                     Item.Item.pc = (CHAR8 *)"(null)";
1110530d68baSNigel Croxon                 }
1111530d68baSNigel Croxon                 break;
1112530d68baSNigel Croxon 
1113530d68baSNigel Croxon             case 's':
1114530d68baSNigel Croxon                 Item.Item.pw = va_arg(ps->args, CHAR16 *);
1115530d68baSNigel Croxon                 if (!Item.Item.pw) {
1116530d68baSNigel Croxon                     Item.Item.pw = L"(null)";
1117530d68baSNigel Croxon                 }
1118530d68baSNigel Croxon                 break;
1119530d68baSNigel Croxon 
1120530d68baSNigel Croxon             case 'c':
1121530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1122530d68baSNigel Croxon                 Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
1123530d68baSNigel Croxon                 Item.Item.pw[1] = 0;
1124530d68baSNigel Croxon                 break;
1125530d68baSNigel Croxon 
1126530d68baSNigel Croxon             case 'l':
1127530d68baSNigel Croxon                 Item.Long = TRUE;
1128530d68baSNigel Croxon                 break;
1129530d68baSNigel Croxon 
1130530d68baSNigel Croxon             case 'X':
1131530d68baSNigel Croxon                 Item.Width = Item.Long ? 16 : 8;
1132530d68baSNigel Croxon                 Item.Pad = '0';
1133530d68baSNigel Croxon             case 'x':
1134530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1135530d68baSNigel Croxon                 ValueToHex (
1136530d68baSNigel Croxon                     Item.Item.pw,
1137530d68baSNigel Croxon                     Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1138530d68baSNigel Croxon                     );
1139530d68baSNigel Croxon 
1140530d68baSNigel Croxon                 break;
1141530d68baSNigel Croxon 
1142530d68baSNigel Croxon 
1143530d68baSNigel Croxon             case 'g':
1144530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1145530d68baSNigel Croxon                 GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
1146530d68baSNigel Croxon                 break;
1147530d68baSNigel Croxon 
1148*1acb1d9dSNigel Croxon             case 'u':
1149530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1150530d68baSNigel Croxon                 ValueToString (
1151530d68baSNigel Croxon                     Item.Item.pw,
1152530d68baSNigel Croxon                     Item.Comma,
1153530d68baSNigel Croxon                     Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1154530d68baSNigel Croxon                     );
1155*1acb1d9dSNigel Croxon                 break;
1156*1acb1d9dSNigel Croxon 
1157*1acb1d9dSNigel Croxon             case 'd':
1158*1acb1d9dSNigel Croxon                 Item.Item.pw = Item.Scratch;
1159*1acb1d9dSNigel Croxon                 ValueToString (
1160*1acb1d9dSNigel Croxon                     Item.Item.pw,
1161*1acb1d9dSNigel Croxon                     Item.Comma,
1162*1acb1d9dSNigel Croxon                     Item.Long ? va_arg(ps->args, INT64) : va_arg(ps->args, INT32)
1163*1acb1d9dSNigel Croxon                     );
1164*1acb1d9dSNigel Croxon                 break;
1165*1acb1d9dSNigel Croxon 
1166530d68baSNigel Croxon             case 't':
1167530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1168530d68baSNigel Croxon                 TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
1169530d68baSNigel Croxon                 break;
1170530d68baSNigel Croxon 
1171530d68baSNigel Croxon             case 'r':
1172530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1173530d68baSNigel Croxon                 StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
1174530d68baSNigel Croxon                 break;
1175530d68baSNigel Croxon 
1176530d68baSNigel Croxon             case 'n':
1177530d68baSNigel Croxon                 PSETATTR(ps, ps->AttrNorm);
1178530d68baSNigel Croxon                 break;
1179530d68baSNigel Croxon 
1180530d68baSNigel Croxon             case 'h':
1181530d68baSNigel Croxon                 PSETATTR(ps, ps->AttrHighlight);
1182530d68baSNigel Croxon                 break;
1183530d68baSNigel Croxon 
1184530d68baSNigel Croxon             case 'e':
1185530d68baSNigel Croxon                 PSETATTR(ps, ps->AttrError);
1186530d68baSNigel Croxon                 break;
1187530d68baSNigel Croxon 
1188530d68baSNigel Croxon             case 'N':
1189530d68baSNigel Croxon                 Attr = ps->AttrNorm;
1190530d68baSNigel Croxon                 break;
1191530d68baSNigel Croxon 
1192530d68baSNigel Croxon             case 'H':
1193530d68baSNigel Croxon                 Attr = ps->AttrHighlight;
1194530d68baSNigel Croxon                 break;
1195530d68baSNigel Croxon 
1196530d68baSNigel Croxon             case 'E':
1197530d68baSNigel Croxon                 Attr = ps->AttrError;
1198530d68baSNigel Croxon                 break;
1199530d68baSNigel Croxon 
1200530d68baSNigel Croxon             default:
1201530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1202530d68baSNigel Croxon                 Item.Item.pw[0] = '?';
1203530d68baSNigel Croxon                 Item.Item.pw[1] = 0;
1204530d68baSNigel Croxon                 break;
1205530d68baSNigel Croxon             }
1206530d68baSNigel Croxon 
1207530d68baSNigel Croxon             // if we have an Item
1208530d68baSNigel Croxon             if (Item.Item.pw) {
1209530d68baSNigel Croxon                 PITEM (ps);
1210530d68baSNigel Croxon                 break;
1211530d68baSNigel Croxon             }
1212530d68baSNigel Croxon 
1213530d68baSNigel Croxon             // if we have an Attr set
1214530d68baSNigel Croxon             if (Attr) {
1215530d68baSNigel Croxon                 PSETATTR(ps, Attr);
1216530d68baSNigel Croxon                 ps->RestoreAttr = 0;
1217530d68baSNigel Croxon                 break;
1218530d68baSNigel Croxon             }
1219530d68baSNigel Croxon         }
1220530d68baSNigel Croxon 
1221530d68baSNigel Croxon         if (ps->RestoreAttr) {
1222530d68baSNigel Croxon             PSETATTR(ps, ps->RestoreAttr);
1223530d68baSNigel Croxon         }
1224530d68baSNigel Croxon     }
1225530d68baSNigel Croxon 
1226530d68baSNigel Croxon     // Flush buffer
1227530d68baSNigel Croxon     PFLUSH (ps);
1228530d68baSNigel Croxon     return ps->Len;
1229530d68baSNigel Croxon }
1230530d68baSNigel Croxon 
1231530d68baSNigel Croxon STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
1232530d68baSNigel Croxon                       '8','9','A','B','C','D','E','F'};
1233530d68baSNigel Croxon 
1234530d68baSNigel Croxon VOID
1235530d68baSNigel Croxon ValueToHex (
1236530d68baSNigel Croxon     IN CHAR16   *Buffer,
1237530d68baSNigel Croxon     IN UINT64   v
1238530d68baSNigel Croxon     )
1239530d68baSNigel Croxon {
1240530d68baSNigel Croxon     CHAR8           str[30], *p1;
1241530d68baSNigel Croxon     CHAR16          *p2;
1242530d68baSNigel Croxon 
1243530d68baSNigel Croxon     if (!v) {
1244530d68baSNigel Croxon         Buffer[0] = '0';
1245530d68baSNigel Croxon         Buffer[1] = 0;
1246530d68baSNigel Croxon         return ;
1247530d68baSNigel Croxon     }
1248530d68baSNigel Croxon 
1249530d68baSNigel Croxon     p1 = str;
1250530d68baSNigel Croxon     p2 = Buffer;
1251530d68baSNigel Croxon 
1252530d68baSNigel Croxon     while (v) {
1253530d68baSNigel Croxon         *(p1++) = Hex[v & 0xf];
1254530d68baSNigel Croxon         v = RShiftU64 (v, 4);
1255530d68baSNigel Croxon     }
1256530d68baSNigel Croxon 
1257530d68baSNigel Croxon     while (p1 != str) {
1258530d68baSNigel Croxon         *(p2++) = *(--p1);
1259530d68baSNigel Croxon     }
1260530d68baSNigel Croxon     *p2 = 0;
1261530d68baSNigel Croxon }
1262530d68baSNigel Croxon 
1263530d68baSNigel Croxon 
1264530d68baSNigel Croxon VOID
1265530d68baSNigel Croxon ValueToString (
1266530d68baSNigel Croxon     IN CHAR16   *Buffer,
1267530d68baSNigel Croxon     IN BOOLEAN  Comma,
1268530d68baSNigel Croxon     IN INT64    v
1269530d68baSNigel Croxon     )
1270530d68baSNigel Croxon {
1271530d68baSNigel Croxon     STATIC CHAR8 ca[] = {  3, 1, 2 };
1272530d68baSNigel Croxon     CHAR8        str[40], *p1;
1273530d68baSNigel Croxon     CHAR16       *p2;
1274530d68baSNigel Croxon     UINTN        c, r;
1275530d68baSNigel Croxon 
1276530d68baSNigel Croxon     if (!v) {
1277530d68baSNigel Croxon         Buffer[0] = '0';
1278530d68baSNigel Croxon         Buffer[1] = 0;
1279530d68baSNigel Croxon         return ;
1280530d68baSNigel Croxon     }
1281530d68baSNigel Croxon 
1282530d68baSNigel Croxon     p1 = str;
1283530d68baSNigel Croxon     p2 = Buffer;
1284530d68baSNigel Croxon 
1285530d68baSNigel Croxon     if (v < 0) {
1286530d68baSNigel Croxon         *(p2++) = '-';
1287530d68baSNigel Croxon         v = -v;
1288530d68baSNigel Croxon     }
1289530d68baSNigel Croxon 
1290530d68baSNigel Croxon     while (v) {
1291530d68baSNigel Croxon         v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
1292530d68baSNigel Croxon         *(p1++) = (CHAR8)r + '0';
1293530d68baSNigel Croxon     }
1294530d68baSNigel Croxon 
1295530d68baSNigel Croxon     c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
1296530d68baSNigel Croxon     while (p1 != str) {
1297530d68baSNigel Croxon 
1298530d68baSNigel Croxon         c -= 1;
1299530d68baSNigel Croxon         if (!c) {
1300530d68baSNigel Croxon             *(p2++) = ',';
1301530d68baSNigel Croxon             c = 3;
1302530d68baSNigel Croxon         }
1303530d68baSNigel Croxon 
1304530d68baSNigel Croxon         *(p2++) = *(--p1);
1305530d68baSNigel Croxon     }
1306530d68baSNigel Croxon     *p2 = 0;
1307530d68baSNigel Croxon }
1308530d68baSNigel Croxon 
1309530d68baSNigel Croxon VOID
1310530d68baSNigel Croxon TimeToString (
1311530d68baSNigel Croxon     OUT CHAR16      *Buffer,
1312530d68baSNigel Croxon     IN EFI_TIME     *Time
1313530d68baSNigel Croxon     )
1314530d68baSNigel Croxon {
1315530d68baSNigel Croxon     UINTN       Hour, Year;
1316530d68baSNigel Croxon     CHAR16      AmPm;
1317530d68baSNigel Croxon 
1318530d68baSNigel Croxon     AmPm = 'a';
1319530d68baSNigel Croxon     Hour = Time->Hour;
1320530d68baSNigel Croxon     if (Time->Hour == 0) {
1321530d68baSNigel Croxon         Hour = 12;
1322530d68baSNigel Croxon     } else if (Time->Hour >= 12) {
1323530d68baSNigel Croxon         AmPm = 'p';
1324530d68baSNigel Croxon         if (Time->Hour >= 13) {
1325530d68baSNigel Croxon             Hour -= 12;
1326530d68baSNigel Croxon         }
1327530d68baSNigel Croxon     }
1328530d68baSNigel Croxon 
1329530d68baSNigel Croxon     Year = Time->Year % 100;
1330530d68baSNigel Croxon 
1331530d68baSNigel Croxon     // bugbug: for now just print it any old way
1332530d68baSNigel Croxon     SPrint (Buffer, 0, L"%02d/%02d/%02d  %02d:%02d%c",
1333530d68baSNigel Croxon         Time->Month,
1334530d68baSNigel Croxon         Time->Day,
1335530d68baSNigel Croxon         Year,
1336530d68baSNigel Croxon         Hour,
1337530d68baSNigel Croxon         Time->Minute,
1338530d68baSNigel Croxon         AmPm
1339530d68baSNigel Croxon         );
1340530d68baSNigel Croxon }
1341530d68baSNigel Croxon 
1342530d68baSNigel Croxon 
1343530d68baSNigel Croxon 
1344530d68baSNigel Croxon 
1345530d68baSNigel Croxon VOID
1346530d68baSNigel Croxon DumpHex (
1347530d68baSNigel Croxon     IN UINTN        Indent,
1348530d68baSNigel Croxon     IN UINTN        Offset,
1349530d68baSNigel Croxon     IN UINTN        DataSize,
1350530d68baSNigel Croxon     IN VOID         *UserData
1351530d68baSNigel Croxon     )
1352530d68baSNigel Croxon {
1353530d68baSNigel Croxon     CHAR8           *Data, Val[50], Str[20], c;
1354530d68baSNigel Croxon     UINTN           Size, Index;
1355530d68baSNigel Croxon 
1356530d68baSNigel Croxon     UINTN           ScreenCount;
1357530d68baSNigel Croxon     UINTN           TempColumn;
1358530d68baSNigel Croxon     UINTN           ScreenSize;
1359530d68baSNigel Croxon     CHAR16          ReturnStr[1];
1360530d68baSNigel Croxon 
1361530d68baSNigel Croxon 
1362530d68baSNigel Croxon     uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
1363530d68baSNigel Croxon     ScreenCount = 0;
1364530d68baSNigel Croxon     ScreenSize -= 2;
1365530d68baSNigel Croxon 
1366530d68baSNigel Croxon     Data = UserData;
1367530d68baSNigel Croxon     while (DataSize) {
1368530d68baSNigel Croxon         Size = 16;
1369530d68baSNigel Croxon         if (Size > DataSize) {
1370530d68baSNigel Croxon             Size = DataSize;
1371530d68baSNigel Croxon         }
1372530d68baSNigel Croxon 
1373530d68baSNigel Croxon         for (Index=0; Index < Size; Index += 1) {
1374530d68baSNigel Croxon             c = Data[Index];
1375530d68baSNigel Croxon             Val[Index*3+0] = Hex[c>>4];
1376530d68baSNigel Croxon             Val[Index*3+1] = Hex[c&0xF];
1377530d68baSNigel Croxon             Val[Index*3+2] = (Index == 7)?'-':' ';
1378530d68baSNigel Croxon             Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
1379530d68baSNigel Croxon         }
1380530d68baSNigel Croxon 
1381530d68baSNigel Croxon         Val[Index*3] = 0;
1382530d68baSNigel Croxon         Str[Index] = 0;
1383530d68baSNigel Croxon         Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
1384530d68baSNigel Croxon 
1385530d68baSNigel Croxon         Data += Size;
1386530d68baSNigel Croxon         Offset += Size;
1387530d68baSNigel Croxon         DataSize -= Size;
1388530d68baSNigel Croxon 
1389530d68baSNigel Croxon         ScreenCount++;
1390530d68baSNigel Croxon         if (ScreenCount >= ScreenSize && ScreenSize != 0) {
1391530d68baSNigel Croxon             //
1392530d68baSNigel Croxon             // If ScreenSize == 0 we have the console redirected so don't
1393530d68baSNigel Croxon             //  block updates
1394530d68baSNigel Croxon             //
1395530d68baSNigel Croxon             ScreenCount = 0;
1396530d68baSNigel Croxon             Print (L"Press Enter to continue :");
1397530d68baSNigel Croxon             Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
1398530d68baSNigel Croxon             Print (L"\n");
1399530d68baSNigel Croxon         }
1400530d68baSNigel Croxon 
1401530d68baSNigel Croxon     }
1402530d68baSNigel Croxon }
1403