xref: /DragonStub/lib/print.c (revision 4b5db35e9d1f4295fa7a8f393021fd2f433a90e4)
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 {
58fa1b9779SNigel Croxon         CONST CHAR16    *pw;
59fa1b9779SNigel Croxon         CONST 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,
122fa1b9779SNigel Croxon     IN CONST CHAR16                     *fmt,
123fa1b9779SNigel Croxon     IN CONST 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
DbgPrint(IN INTN mask,IN CONST CHAR8 * fmt,...)183530d68baSNigel Croxon DbgPrint (
184530d68baSNigel Croxon     IN INTN         mask,
185fa1b9779SNigel Croxon     IN CONST 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
IsLocalPrint(void * func)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
_DbgOut(IN VOID * Context,IN CHAR16 * Buffer)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
_SPrint(IN VOID * Context,IN CHAR16 * Buffer)314530d68baSNigel Croxon _SPrint (
315530d68baSNigel Croxon     IN VOID     *Context,
316530d68baSNigel Croxon     IN CHAR16   *Buffer
317530d68baSNigel Croxon     )
318b39be0d5SPete Batard // Append string worker for UnicodeSPrint, 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
_PoolPrint(IN VOID * Context,IN CHAR16 * Buffer)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
_PoolCatPrint(IN CONST CHAR16 * fmt,IN va_list args,IN OUT POOL_PRINT * spc,IN INTN (EFIAPI * Output)(VOID * context,CHAR16 * str))402530d68baSNigel Croxon _PoolCatPrint (
403fa1b9779SNigel Croxon     IN CONST 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     )
408b39be0d5SPete Batard // Dispatch function for UnicodeSPrint, 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
UnicodeVSPrint(OUT CHAR16 * Str,IN UINTN StrSize,IN CONST CHAR16 * fmt,va_list args)424b39be0d5SPete Batard UnicodeVSPrint (
425530d68baSNigel Croxon     OUT CHAR16        *Str,
426530d68baSNigel Croxon     IN UINTN          StrSize,
427fa1b9779SNigel Croxon     IN CONST 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
UnicodeSPrint(OUT CHAR16 * Str,IN UINTN StrSize,IN CONST CHAR16 * fmt,...)466b39be0d5SPete Batard UnicodeSPrint (
467530d68baSNigel Croxon     OUT CHAR16        *Str,
468530d68baSNigel Croxon     IN UINTN          StrSize,
469fa1b9779SNigel Croxon     IN CONST 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);
497b39be0d5SPete Batard     len = UnicodeVSPrint(Str, StrSize, fmt, args);
498530d68baSNigel Croxon     va_end (args);
499530d68baSNigel Croxon 
500530d68baSNigel Croxon     return len;
501530d68baSNigel Croxon }
502530d68baSNigel Croxon 
503530d68baSNigel Croxon CHAR16 *
VPoolPrint(IN CONST CHAR16 * fmt,va_list args)504530d68baSNigel Croxon VPoolPrint (
505fa1b9779SNigel Croxon     IN CONST 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 *
PoolPrint(IN CONST CHAR16 * fmt,...)535530d68baSNigel Croxon PoolPrint (
536fa1b9779SNigel Croxon     IN CONST 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 *
CatPrint(IN OUT POOL_PRINT * Str,IN CONST CHAR16 * fmt,...)567530d68baSNigel Croxon CatPrint (
568530d68baSNigel Croxon     IN OUT POOL_PRINT   *Str,
569fa1b9779SNigel Croxon     IN CONST 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
Print(IN CONST CHAR16 * fmt,...)605530d68baSNigel Croxon Print (
606fa1b9779SNigel Croxon     IN CONST 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
VPrint(IN CONST CHAR16 * fmt,va_list args)635530d68baSNigel Croxon VPrint (
636fa1b9779SNigel Croxon     IN CONST 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
PrintAt(IN UINTN Column,IN UINTN Row,IN CONST CHAR16 * fmt,...)660530d68baSNigel Croxon PrintAt (
661530d68baSNigel Croxon     IN UINTN          Column,
662530d68baSNigel Croxon     IN UINTN          Row,
663fa1b9779SNigel Croxon     IN CONST 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
IPrint(IN SIMPLE_TEXT_OUTPUT_INTERFACE * Out,IN CONST CHAR16 * fmt,...)696530d68baSNigel Croxon IPrint (
697530d68baSNigel Croxon     IN SIMPLE_TEXT_OUTPUT_INTERFACE    *Out,
698fa1b9779SNigel Croxon     IN CONST 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
IPrintAt(IN SIMPLE_TEXT_OUTPUT_INTERFACE * Out,IN UINTN Column,IN UINTN Row,IN CONST CHAR16 * fmt,...)730530d68baSNigel Croxon IPrintAt (
731530d68baSNigel Croxon     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
732530d68baSNigel Croxon     IN UINTN                            Column,
733530d68baSNigel Croxon     IN UINTN                            Row,
734fa1b9779SNigel Croxon     IN CONST 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
_IPrint(IN UINTN Column,IN UINTN Row,IN SIMPLE_TEXT_OUTPUT_INTERFACE * Out,IN CONST CHAR16 * fmt,IN CONST CHAR8 * fmta,IN va_list args)769530d68baSNigel Croxon _IPrint (
770530d68baSNigel Croxon     IN UINTN                            Column,
771530d68baSNigel Croxon     IN UINTN                            Row,
772530d68baSNigel Croxon     IN SIMPLE_TEXT_OUTPUT_INTERFACE     *Out,
773fa1b9779SNigel Croxon     IN CONST CHAR16                     *fmt,
774fa1b9779SNigel Croxon     IN CONST 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
AsciiPrint(IN CONST CHAR8 * fmt,...)8130247cb7cSPete Batard AsciiPrint (
814fa1b9779SNigel Croxon     IN CONST 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 
8450247cb7cSPete Batard UINTN
AsciiVSPrint(OUT CHAR8 * Str,IN UINTN StrSize,IN CONST CHAR8 * fmt,va_list args)8460247cb7cSPete Batard AsciiVSPrint (
8470247cb7cSPete Batard     OUT CHAR8         *Str,
8480247cb7cSPete Batard     IN UINTN          StrSize,
8490247cb7cSPete Batard     IN CONST CHAR8    *fmt,
8500247cb7cSPete Batard     va_list           args
8510247cb7cSPete Batard )
8520247cb7cSPete Batard /*++
8530247cb7cSPete Batard 
8540247cb7cSPete Batard Routine Description:
8550247cb7cSPete Batard 
8560247cb7cSPete Batard     Prints a formatted ascii string to a buffer using a va_list
8570247cb7cSPete Batard 
8580247cb7cSPete Batard Arguments:
8590247cb7cSPete Batard 
8600247cb7cSPete Batard     Str         - Output buffer to print the formatted string into
8610247cb7cSPete Batard 
8620247cb7cSPete Batard     StrSize     - Size of Str.  String is truncated to this size.
8630247cb7cSPete Batard                   A size of 0 means there is no limit
8640247cb7cSPete Batard 
8650247cb7cSPete Batard     fmt         - The format string
8660247cb7cSPete Batard 
8670247cb7cSPete Batard     args        - va_list
8680247cb7cSPete Batard 
8690247cb7cSPete Batard 
8700247cb7cSPete Batard Returns:
8710247cb7cSPete Batard 
8720247cb7cSPete Batard     String length returned in buffer
8730247cb7cSPete Batard 
8740247cb7cSPete Batard --*/
8750247cb7cSPete Batard // Use UnicodeVSPrint() and convert back to ASCII
8760247cb7cSPete Batard {
8770247cb7cSPete Batard     CHAR16 *UnicodeStr, *UnicodeFmt;
8780247cb7cSPete Batard     UINTN i, Len;
8790247cb7cSPete Batard 
8800247cb7cSPete Batard     UnicodeStr = AllocatePool(StrSize * sizeof(CHAR16));
8810247cb7cSPete Batard     if (!UnicodeStr)
8820247cb7cSPete Batard         return 0;
8830247cb7cSPete Batard 
8840247cb7cSPete Batard     UnicodeFmt = PoolPrint(L"%a", fmt);
8850247cb7cSPete Batard     if (!UnicodeFmt) {
8860247cb7cSPete Batard         FreePool(UnicodeStr);
8870247cb7cSPete Batard         return 0;
8880247cb7cSPete Batard     }
8890247cb7cSPete Batard 
890b39be0d5SPete Batard     Len = UnicodeVSPrint(UnicodeStr, StrSize, UnicodeFmt, args);
8910247cb7cSPete Batard     FreePool(UnicodeFmt);
8920247cb7cSPete Batard 
8930247cb7cSPete Batard     // The strings are ASCII so just do a plain Unicode conversion
8940247cb7cSPete Batard     for (i = 0; i < Len; i++)
8950247cb7cSPete Batard         Str[i] = (CHAR8)UnicodeStr[i];
8960247cb7cSPete Batard     Str[Len] = 0;
8970247cb7cSPete Batard     FreePool(UnicodeStr);
8980247cb7cSPete Batard 
8990247cb7cSPete Batard     return Len;
9000247cb7cSPete Batard }
9010247cb7cSPete Batard 
9020247cb7cSPete Batard 
903530d68baSNigel Croxon STATIC
904530d68baSNigel Croxon VOID
PFLUSH(IN OUT PRINT_STATE * ps)905530d68baSNigel Croxon PFLUSH (
906530d68baSNigel Croxon     IN OUT PRINT_STATE     *ps
907530d68baSNigel Croxon     )
908530d68baSNigel Croxon {
909530d68baSNigel Croxon     *ps->Pos = 0;
910530d68baSNigel Croxon     if (IsLocalPrint(ps->Output))
911530d68baSNigel Croxon 	ps->Output(ps->Context, ps->Buffer);
912530d68baSNigel Croxon     else
913530d68baSNigel Croxon     	uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
914530d68baSNigel Croxon     ps->Pos = ps->Buffer;
915530d68baSNigel Croxon }
916530d68baSNigel Croxon 
917530d68baSNigel Croxon STATIC
918530d68baSNigel Croxon VOID
PSETATTR(IN OUT PRINT_STATE * ps,IN UINTN Attr)919530d68baSNigel Croxon PSETATTR (
920530d68baSNigel Croxon     IN OUT PRINT_STATE  *ps,
921530d68baSNigel Croxon     IN UINTN             Attr
922530d68baSNigel Croxon     )
923530d68baSNigel Croxon {
924530d68baSNigel Croxon    PFLUSH (ps);
925530d68baSNigel Croxon 
926530d68baSNigel Croxon    ps->RestoreAttr = ps->Attr;
927530d68baSNigel Croxon    if (ps->SetAttr) {
928530d68baSNigel Croxon 	uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
929530d68baSNigel Croxon    }
930530d68baSNigel Croxon 
931530d68baSNigel Croxon    ps->Attr = Attr;
932530d68baSNigel Croxon }
933530d68baSNigel Croxon 
934530d68baSNigel Croxon STATIC
935530d68baSNigel Croxon VOID
PPUTC(IN OUT PRINT_STATE * ps,IN CHAR16 c)936530d68baSNigel Croxon PPUTC (
937530d68baSNigel Croxon     IN OUT PRINT_STATE     *ps,
938530d68baSNigel Croxon     IN CHAR16              c
939530d68baSNigel Croxon     )
940530d68baSNigel Croxon {
941530d68baSNigel Croxon     // if this is a newline, add a carraige return
942530d68baSNigel Croxon     if (c == '\n') {
943530d68baSNigel Croxon         PPUTC (ps, '\r');
944530d68baSNigel Croxon     }
945530d68baSNigel Croxon 
946530d68baSNigel Croxon     *ps->Pos = c;
947530d68baSNigel Croxon     ps->Pos += 1;
948530d68baSNigel Croxon     ps->Len += 1;
949530d68baSNigel Croxon 
950530d68baSNigel Croxon     // if at the end of the buffer, flush it
951530d68baSNigel Croxon     if (ps->Pos >= ps->End) {
952530d68baSNigel Croxon         PFLUSH(ps);
953530d68baSNigel Croxon     }
954530d68baSNigel Croxon }
955530d68baSNigel Croxon 
956530d68baSNigel Croxon 
957530d68baSNigel Croxon STATIC
958530d68baSNigel Croxon CHAR16
PGETC(IN POINTER * p)959530d68baSNigel Croxon PGETC (
960530d68baSNigel Croxon     IN POINTER      *p
961530d68baSNigel Croxon     )
962530d68baSNigel Croxon {
963530d68baSNigel Croxon     CHAR16      c;
964530d68baSNigel Croxon 
965530d68baSNigel Croxon     c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
966530d68baSNigel Croxon     p->Index += 1;
967530d68baSNigel Croxon 
968530d68baSNigel Croxon     return  c;
969530d68baSNigel Croxon }
970530d68baSNigel Croxon 
971530d68baSNigel Croxon 
972530d68baSNigel Croxon STATIC
973530d68baSNigel Croxon VOID
PITEM(IN OUT PRINT_STATE * ps)974530d68baSNigel Croxon PITEM (
975530d68baSNigel Croxon     IN OUT PRINT_STATE  *ps
976530d68baSNigel Croxon     )
977530d68baSNigel Croxon {
978530d68baSNigel Croxon     UINTN               Len, i;
979530d68baSNigel Croxon     PRINT_ITEM          *Item;
980530d68baSNigel Croxon     CHAR16              c;
981530d68baSNigel Croxon 
982530d68baSNigel Croxon     // Get the length of the item
983530d68baSNigel Croxon     Item = ps->Item;
984530d68baSNigel Croxon     Item->Item.Index = 0;
985530d68baSNigel Croxon     while (Item->Item.Index < Item->FieldWidth) {
986530d68baSNigel Croxon         c = PGETC(&Item->Item);
987530d68baSNigel Croxon         if (!c) {
988530d68baSNigel Croxon             Item->Item.Index -= 1;
989530d68baSNigel Croxon             break;
990530d68baSNigel Croxon         }
991530d68baSNigel Croxon     }
992530d68baSNigel Croxon     Len = Item->Item.Index;
993530d68baSNigel Croxon 
994530d68baSNigel Croxon     // if there is no item field width, use the items width
995530d68baSNigel Croxon     if (Item->FieldWidth == (UINTN) -1) {
996530d68baSNigel Croxon         Item->FieldWidth = Len;
997530d68baSNigel Croxon     }
998530d68baSNigel Croxon 
999530d68baSNigel Croxon     // if item is larger then width, update width
1000530d68baSNigel Croxon     if (Len > Item->Width) {
1001530d68baSNigel Croxon         Item->Width = Len;
1002530d68baSNigel Croxon     }
1003530d68baSNigel Croxon 
1004530d68baSNigel Croxon 
1005530d68baSNigel Croxon     // if pad field before, add pad char
1006530d68baSNigel Croxon     if (Item->PadBefore) {
1007530d68baSNigel Croxon         for (i=Item->Width; i < Item->FieldWidth; i+=1) {
1008530d68baSNigel Croxon             PPUTC (ps, ' ');
1009530d68baSNigel Croxon         }
1010530d68baSNigel Croxon     }
1011530d68baSNigel Croxon 
1012530d68baSNigel Croxon     // pad item
1013530d68baSNigel Croxon     for (i=Len; i < Item->Width; i++) {
1014530d68baSNigel Croxon         PPUTC (ps, Item->Pad);
1015530d68baSNigel Croxon     }
1016530d68baSNigel Croxon 
1017530d68baSNigel Croxon     // add the item
1018530d68baSNigel Croxon     Item->Item.Index=0;
1019530d68baSNigel Croxon     while (Item->Item.Index < Len) {
1020530d68baSNigel Croxon         PPUTC (ps, PGETC(&Item->Item));
1021530d68baSNigel Croxon     }
1022530d68baSNigel Croxon 
1023530d68baSNigel Croxon     // If pad at the end, add pad char
1024530d68baSNigel Croxon     if (!Item->PadBefore) {
1025530d68baSNigel Croxon         for (i=Item->Width; i < Item->FieldWidth; i+=1) {
1026530d68baSNigel Croxon             PPUTC (ps, ' ');
1027530d68baSNigel Croxon         }
1028530d68baSNigel Croxon     }
1029530d68baSNigel Croxon }
1030530d68baSNigel Croxon 
1031530d68baSNigel Croxon 
1032530d68baSNigel Croxon STATIC
1033530d68baSNigel Croxon UINTN
_Print(IN PRINT_STATE * ps)1034530d68baSNigel Croxon _Print (
1035530d68baSNigel Croxon     IN PRINT_STATE     *ps
1036530d68baSNigel Croxon     )
1037530d68baSNigel Croxon /*++
1038530d68baSNigel Croxon 
1039530d68baSNigel Croxon Routine Description:
1040530d68baSNigel Croxon 
1041530d68baSNigel Croxon     %w.lF   -   w = width
1042530d68baSNigel Croxon                 l = field width
1043530d68baSNigel Croxon                 F = format of arg
1044530d68baSNigel Croxon 
1045530d68baSNigel Croxon   Args F:
1046530d68baSNigel Croxon     0       -   pad with zeros
1047530d68baSNigel Croxon     -       -   justify on left (default is on right)
1048530d68baSNigel Croxon     ,       -   add comma's to field
1049530d68baSNigel Croxon     *       -   width provided on stack
1050530d68baSNigel Croxon     n       -   Set output attribute to normal (for this field only)
1051530d68baSNigel Croxon     h       -   Set output attribute to highlight (for this field only)
1052530d68baSNigel Croxon     e       -   Set output attribute to error (for this field only)
1053530d68baSNigel Croxon     l       -   Value is 64 bits
1054530d68baSNigel Croxon 
1055530d68baSNigel Croxon     a       -   ascii string
1056530d68baSNigel Croxon     s       -   unicode string
1057530d68baSNigel Croxon     X       -   fixed 8 byte value in hex
1058530d68baSNigel Croxon     x       -   hex value
10591acb1d9dSNigel Croxon     d       -   value as signed decimal
10601acb1d9dSNigel Croxon     u       -   value as unsigned decimal
1061b2c4db06SNigel Croxon     f       -   value as floating point
1062530d68baSNigel Croxon     c       -   Unicode char
1063530d68baSNigel Croxon     t       -   EFI time structure
1064530d68baSNigel Croxon     g       -   Pointer to GUID
1065530d68baSNigel Croxon     r       -   EFI status code (result code)
106628793041SPeter Jones     D       -   pointer to Device Path with normal ending.
1067530d68baSNigel Croxon 
1068530d68baSNigel Croxon     N       -   Set output attribute to normal
1069530d68baSNigel Croxon     H       -   Set output attribute to highlight
1070530d68baSNigel Croxon     E       -   Set output attribute to error
1071530d68baSNigel Croxon     %       -   Print a %
1072530d68baSNigel Croxon 
1073530d68baSNigel Croxon Arguments:
1074530d68baSNigel Croxon 
1075530d68baSNigel Croxon     SystemTable     - The system table
1076530d68baSNigel Croxon 
1077530d68baSNigel Croxon Returns:
1078530d68baSNigel Croxon 
1079530d68baSNigel Croxon     Number of charactors written
1080530d68baSNigel Croxon 
1081530d68baSNigel Croxon --*/
1082530d68baSNigel Croxon {
1083530d68baSNigel Croxon     CHAR16          c;
1084530d68baSNigel Croxon     UINTN           Attr;
1085530d68baSNigel Croxon     PRINT_ITEM      Item;
1086530d68baSNigel Croxon     CHAR16          Buffer[PRINT_STRING_LEN];
1087530d68baSNigel Croxon 
1088530d68baSNigel Croxon     ps->Len = 0;
1089530d68baSNigel Croxon     ps->Buffer = Buffer;
1090530d68baSNigel Croxon     ps->Pos = Buffer;
1091530d68baSNigel Croxon     ps->End = Buffer + PRINT_STRING_LEN - 1;
1092530d68baSNigel Croxon     ps->Item = &Item;
1093530d68baSNigel Croxon 
1094530d68baSNigel Croxon     ps->fmt.Index = 0;
1095530d68baSNigel Croxon     while ((c = PGETC(&ps->fmt))) {
1096530d68baSNigel Croxon 
1097530d68baSNigel Croxon         if (c != '%') {
1098530d68baSNigel Croxon             PPUTC ( ps, c );
1099530d68baSNigel Croxon             continue;
1100530d68baSNigel Croxon         }
1101530d68baSNigel Croxon 
1102530d68baSNigel Croxon         // setup for new item
1103530d68baSNigel Croxon         Item.FieldWidth = (UINTN) -1;
1104530d68baSNigel Croxon         Item.Width = 0;
1105530d68baSNigel Croxon         Item.WidthParse = &Item.Width;
1106530d68baSNigel Croxon         Item.Pad = ' ';
1107530d68baSNigel Croxon         Item.PadBefore = TRUE;
1108530d68baSNigel Croxon         Item.Comma = FALSE;
1109530d68baSNigel Croxon         Item.Long = FALSE;
1110530d68baSNigel Croxon         Item.Item.Ascii = FALSE;
1111530d68baSNigel Croxon         Item.Item.pw = NULL;
1112530d68baSNigel Croxon         ps->RestoreAttr = 0;
1113530d68baSNigel Croxon         Attr = 0;
1114530d68baSNigel Croxon 
1115530d68baSNigel Croxon         while ((c = PGETC(&ps->fmt))) {
1116530d68baSNigel Croxon 
1117530d68baSNigel Croxon             switch (c) {
1118530d68baSNigel Croxon 
1119530d68baSNigel Croxon             case '%':
1120530d68baSNigel Croxon                 //
1121530d68baSNigel Croxon                 // %% -> %
1122530d68baSNigel Croxon                 //
1123fa1b9779SNigel Croxon                 Item.Scratch[0] = '%';
1124fa1b9779SNigel Croxon                 Item.Scratch[1] = 0;
1125530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1126530d68baSNigel Croxon                 break;
1127530d68baSNigel Croxon 
1128f7bf4302SPeter Jones             case ',':
1129f7bf4302SPeter Jones                 Item.Comma = TRUE;
1130530d68baSNigel Croxon                 break;
1131530d68baSNigel Croxon 
1132530d68baSNigel Croxon             case '-':
1133530d68baSNigel Croxon                 Item.PadBefore = FALSE;
1134530d68baSNigel Croxon                 break;
1135530d68baSNigel Croxon 
1136f7bf4302SPeter Jones             case '*':
1137f7bf4302SPeter Jones                 *Item.WidthParse = va_arg(ps->args, UINTN);
1138530d68baSNigel Croxon                 break;
1139530d68baSNigel Croxon 
1140530d68baSNigel Croxon             case '.':
1141530d68baSNigel Croxon                 Item.WidthParse = &Item.FieldWidth;
1142530d68baSNigel Croxon                 break;
1143530d68baSNigel Croxon 
1144f7bf4302SPeter Jones             case '0':
1145f7bf4302SPeter Jones                 Item.Pad = '0';
1146530d68baSNigel Croxon                 break;
1147530d68baSNigel Croxon 
1148530d68baSNigel Croxon             case '1':
1149530d68baSNigel Croxon             case '2':
1150530d68baSNigel Croxon             case '3':
1151530d68baSNigel Croxon             case '4':
1152530d68baSNigel Croxon             case '5':
1153530d68baSNigel Croxon             case '6':
1154530d68baSNigel Croxon             case '7':
1155530d68baSNigel Croxon             case '8':
1156530d68baSNigel Croxon             case '9':
1157530d68baSNigel Croxon                 *Item.WidthParse = 0;
1158530d68baSNigel Croxon                 do {
1159530d68baSNigel Croxon                     *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
1160530d68baSNigel Croxon                     c = PGETC(&ps->fmt);
1161530d68baSNigel Croxon                 } while (c >= '0'  &&  c <= '9') ;
1162530d68baSNigel Croxon                 ps->fmt.Index -= 1;
1163530d68baSNigel Croxon                 break;
1164530d68baSNigel Croxon 
1165530d68baSNigel Croxon             case 'a':
1166530d68baSNigel Croxon                 Item.Item.pc = va_arg(ps->args, CHAR8 *);
1167530d68baSNigel Croxon                 Item.Item.Ascii = TRUE;
1168530d68baSNigel Croxon                 if (!Item.Item.pc) {
1169530d68baSNigel Croxon                     Item.Item.pc = (CHAR8 *)"(null)";
1170530d68baSNigel Croxon                 }
1171530d68baSNigel Croxon                 break;
1172530d68baSNigel Croxon 
1173530d68baSNigel Croxon             case 'c':
1174fa1b9779SNigel Croxon                 Item.Scratch[0] = (CHAR16) va_arg(ps->args, UINTN);
1175fa1b9779SNigel Croxon                 Item.Scratch[1] = 0;
1176530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1177530d68baSNigel Croxon                 break;
1178530d68baSNigel Croxon 
117928793041SPeter Jones             case 'D':
118028793041SPeter Jones             {
118128793041SPeter Jones                 EFI_DEVICE_PATH *dp = va_arg(ps->args, EFI_DEVICE_PATH *);
118228793041SPeter Jones                 CHAR16 *dpstr = DevicePathToStr(dp);
118328793041SPeter Jones                 StrnCpy(Item.Scratch, dpstr, PRINT_ITEM_BUFFER_LEN);
118428793041SPeter Jones                 Item.Scratch[PRINT_ITEM_BUFFER_LEN-1] = L'\0';
118528793041SPeter Jones                 FreePool(dpstr);
118628793041SPeter Jones 
118728793041SPeter Jones                 Item.Item.pw = Item.Scratch;
118828793041SPeter Jones                 break;
118928793041SPeter Jones             }
119028793041SPeter Jones 
1191f7bf4302SPeter Jones             case 'd':
1192f7bf4302SPeter Jones                 ValueToString (
1193f7bf4302SPeter Jones                     Item.Scratch,
1194f7bf4302SPeter Jones                     Item.Comma,
1195f7bf4302SPeter Jones                     Item.Long ? va_arg(ps->args, INT64) : va_arg(ps->args, INT32)
1196f7bf4302SPeter Jones                     );
1197f7bf4302SPeter Jones                 Item.Item.pw = Item.Scratch;
1198f7bf4302SPeter Jones                 break;
1199f7bf4302SPeter Jones 
1200f7bf4302SPeter Jones             case 'E':
1201f7bf4302SPeter Jones                 Attr = ps->AttrError;
1202f7bf4302SPeter Jones                 break;
1203f7bf4302SPeter Jones 
1204f7bf4302SPeter Jones             case 'e':
1205f7bf4302SPeter Jones                 PSETATTR(ps, ps->AttrError);
1206f7bf4302SPeter Jones                 break;
1207f7bf4302SPeter Jones 
1208b2c4db06SNigel Croxon             case 'f':
1209b2c4db06SNigel Croxon                 FloatToString (
1210fa1b9779SNigel Croxon                     Item.Scratch,
1211b2c4db06SNigel Croxon                     Item.Comma,
1212b2c4db06SNigel Croxon                     va_arg(ps->args, double)
1213b2c4db06SNigel Croxon                     );
1214fa1b9779SNigel Croxon                 Item.Item.pw = Item.Scratch;
1215b2c4db06SNigel Croxon                 break;
1216b2c4db06SNigel Croxon 
1217f7bf4302SPeter Jones             case 'g':
1218f7bf4302SPeter Jones                 GuidToString (Item.Scratch, va_arg(ps->args, EFI_GUID *));
1219530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1220530d68baSNigel Croxon                 break;
1221530d68baSNigel Croxon 
1222f7bf4302SPeter Jones             case 'H':
1223f7bf4302SPeter Jones                 Attr = ps->AttrHighlight;
1224f7bf4302SPeter Jones                 break;
1225f7bf4302SPeter Jones 
1226f7bf4302SPeter Jones             case 'h':
1227f7bf4302SPeter Jones                 PSETATTR(ps, ps->AttrHighlight);
1228f7bf4302SPeter Jones                 break;
1229f7bf4302SPeter Jones 
1230f7bf4302SPeter Jones             case 'l':
1231f7bf4302SPeter Jones                 Item.Long = TRUE;
1232f7bf4302SPeter Jones                 break;
1233f7bf4302SPeter Jones 
1234f7bf4302SPeter Jones             case 'N':
1235f7bf4302SPeter Jones                 Attr = ps->AttrNorm;
1236f7bf4302SPeter Jones                 break;
1237f7bf4302SPeter Jones 
1238f7bf4302SPeter Jones             case 'n':
1239f7bf4302SPeter Jones                 PSETATTR(ps, ps->AttrNorm);
1240f7bf4302SPeter Jones                 break;
1241f7bf4302SPeter Jones 
1242*4b5db35eSPeter Jones             case 'p':
1243*4b5db35eSPeter Jones                 Item.Width = sizeof(void *) == (8 ? 16 : 8) + 2;
1244*4b5db35eSPeter Jones                 Item.Pad = '0';
1245*4b5db35eSPeter Jones                 Item.Scratch[0] = ' ';
1246*4b5db35eSPeter Jones                 Item.Scratch[1] = ' ';
1247*4b5db35eSPeter Jones                 ValueToHex (
1248*4b5db35eSPeter Jones                     Item.Scratch+2,
1249*4b5db35eSPeter Jones                     Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1250*4b5db35eSPeter Jones                     );
1251*4b5db35eSPeter Jones                 Item.Scratch[0] = '0';
1252*4b5db35eSPeter Jones                 Item.Scratch[1] = 'x';
1253*4b5db35eSPeter Jones                 Item.Item.pw = Item.Scratch;
1254*4b5db35eSPeter Jones                 break;
1255*4b5db35eSPeter Jones 
1256530d68baSNigel Croxon             case 'r':
1257fa1b9779SNigel Croxon                 StatusToString (Item.Scratch, va_arg(ps->args, EFI_STATUS));
1258530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1259530d68baSNigel Croxon                 break;
1260530d68baSNigel Croxon 
1261f7bf4302SPeter Jones             case 's':
1262f7bf4302SPeter Jones                 Item.Item.pw = va_arg(ps->args, CHAR16 *);
1263f7bf4302SPeter Jones                 if (!Item.Item.pw) {
1264f7bf4302SPeter Jones                     Item.Item.pw = L"(null)";
1265f7bf4302SPeter Jones                 }
1266530d68baSNigel Croxon                 break;
1267530d68baSNigel Croxon 
1268f7bf4302SPeter Jones             case 't':
1269f7bf4302SPeter Jones                 TimeToString (Item.Scratch, va_arg(ps->args, EFI_TIME *));
1270f7bf4302SPeter Jones                 Item.Item.pw = Item.Scratch;
1271530d68baSNigel Croxon                 break;
1272530d68baSNigel Croxon 
1273f7bf4302SPeter Jones             case 'u':
1274f7bf4302SPeter Jones                 ValueToString (
1275f7bf4302SPeter Jones                     Item.Scratch,
1276f7bf4302SPeter Jones                     Item.Comma,
1277f7bf4302SPeter Jones                     Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1278f7bf4302SPeter Jones                     );
1279f7bf4302SPeter Jones                 Item.Item.pw = Item.Scratch;
1280530d68baSNigel Croxon                 break;
1281530d68baSNigel Croxon 
1282f7bf4302SPeter Jones             case 'X':
1283f7bf4302SPeter Jones                 Item.Width = Item.Long ? 16 : 8;
1284f7bf4302SPeter Jones                 Item.Pad = '0';
1285f7bf4302SPeter Jones #if __GNUC__ >= 7
1286f7bf4302SPeter Jones 		__attribute__ ((fallthrough));
1287f7bf4302SPeter Jones #endif
1288f7bf4302SPeter Jones             case 'x':
1289f7bf4302SPeter Jones                 ValueToHex (
1290f7bf4302SPeter Jones                     Item.Scratch,
1291f7bf4302SPeter Jones                     Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
1292f7bf4302SPeter Jones                     );
1293f7bf4302SPeter Jones                 Item.Item.pw = Item.Scratch;
1294530d68baSNigel Croxon                 break;
1295530d68baSNigel Croxon 
1296530d68baSNigel Croxon             default:
1297fa1b9779SNigel Croxon                 Item.Scratch[0] = '?';
1298fa1b9779SNigel Croxon                 Item.Scratch[1] = 0;
1299530d68baSNigel Croxon                 Item.Item.pw = Item.Scratch;
1300530d68baSNigel Croxon                 break;
1301530d68baSNigel Croxon             }
1302530d68baSNigel Croxon 
1303530d68baSNigel Croxon             // if we have an Item
1304530d68baSNigel Croxon             if (Item.Item.pw) {
1305530d68baSNigel Croxon                 PITEM (ps);
1306530d68baSNigel Croxon                 break;
1307530d68baSNigel Croxon             }
1308530d68baSNigel Croxon 
1309530d68baSNigel Croxon             // if we have an Attr set
1310530d68baSNigel Croxon             if (Attr) {
1311530d68baSNigel Croxon                 PSETATTR(ps, Attr);
1312530d68baSNigel Croxon                 ps->RestoreAttr = 0;
1313530d68baSNigel Croxon                 break;
1314530d68baSNigel Croxon             }
1315530d68baSNigel Croxon         }
1316530d68baSNigel Croxon 
1317530d68baSNigel Croxon         if (ps->RestoreAttr) {
1318530d68baSNigel Croxon             PSETATTR(ps, ps->RestoreAttr);
1319530d68baSNigel Croxon         }
1320530d68baSNigel Croxon     }
1321530d68baSNigel Croxon 
1322530d68baSNigel Croxon     // Flush buffer
1323530d68baSNigel Croxon     PFLUSH (ps);
1324530d68baSNigel Croxon     return ps->Len;
1325530d68baSNigel Croxon }
1326530d68baSNigel Croxon 
1327530d68baSNigel Croxon STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
1328530d68baSNigel Croxon                       '8','9','A','B','C','D','E','F'};
1329530d68baSNigel Croxon 
1330530d68baSNigel Croxon VOID
ValueToHex(IN CHAR16 * Buffer,IN UINT64 v)1331530d68baSNigel Croxon ValueToHex (
1332530d68baSNigel Croxon     IN CHAR16   *Buffer,
1333530d68baSNigel Croxon     IN UINT64   v
1334530d68baSNigel Croxon     )
1335530d68baSNigel Croxon {
1336530d68baSNigel Croxon     CHAR8           str[30], *p1;
1337530d68baSNigel Croxon     CHAR16          *p2;
1338530d68baSNigel Croxon 
1339530d68baSNigel Croxon     if (!v) {
1340530d68baSNigel Croxon         Buffer[0] = '0';
1341530d68baSNigel Croxon         Buffer[1] = 0;
1342530d68baSNigel Croxon         return ;
1343530d68baSNigel Croxon     }
1344530d68baSNigel Croxon 
1345530d68baSNigel Croxon     p1 = str;
1346530d68baSNigel Croxon     p2 = Buffer;
1347530d68baSNigel Croxon 
1348530d68baSNigel Croxon     while (v) {
134938c57d52SNigel Croxon         // Without the cast, the MSVC compiler may insert a reference to __allmull
135038c57d52SNigel Croxon         *(p1++) = Hex[(UINTN)(v & 0xf)];
1351530d68baSNigel Croxon         v = RShiftU64 (v, 4);
1352530d68baSNigel Croxon     }
1353530d68baSNigel Croxon 
1354530d68baSNigel Croxon     while (p1 != str) {
1355530d68baSNigel Croxon         *(p2++) = *(--p1);
1356530d68baSNigel Croxon     }
1357530d68baSNigel Croxon     *p2 = 0;
1358530d68baSNigel Croxon }
1359530d68baSNigel Croxon 
1360530d68baSNigel Croxon 
1361530d68baSNigel Croxon VOID
ValueToString(IN CHAR16 * Buffer,IN BOOLEAN Comma,IN INT64 v)1362530d68baSNigel Croxon ValueToString (
1363530d68baSNigel Croxon     IN CHAR16   *Buffer,
1364530d68baSNigel Croxon     IN BOOLEAN  Comma,
1365530d68baSNigel Croxon     IN INT64    v
1366530d68baSNigel Croxon     )
1367530d68baSNigel Croxon {
1368530d68baSNigel Croxon     STATIC CHAR8 ca[] = {  3, 1, 2 };
1369530d68baSNigel Croxon     CHAR8        str[40], *p1;
1370530d68baSNigel Croxon     CHAR16       *p2;
1371530d68baSNigel Croxon     UINTN        c, r;
1372530d68baSNigel Croxon 
1373530d68baSNigel Croxon     if (!v) {
1374530d68baSNigel Croxon         Buffer[0] = '0';
1375530d68baSNigel Croxon         Buffer[1] = 0;
1376530d68baSNigel Croxon         return ;
1377530d68baSNigel Croxon     }
1378530d68baSNigel Croxon 
1379530d68baSNigel Croxon     p1 = str;
1380530d68baSNigel Croxon     p2 = Buffer;
1381530d68baSNigel Croxon 
1382530d68baSNigel Croxon     if (v < 0) {
1383530d68baSNigel Croxon         *(p2++) = '-';
1384530d68baSNigel Croxon         v = -v;
1385530d68baSNigel Croxon     }
1386530d68baSNigel Croxon 
1387530d68baSNigel Croxon     while (v) {
1388530d68baSNigel Croxon         v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
1389530d68baSNigel Croxon         *(p1++) = (CHAR8)r + '0';
1390530d68baSNigel Croxon     }
1391530d68baSNigel Croxon 
13924ef18335SPete Batard     c = (UINTN) (Comma ? ca[(p1 - str) % 3] : 999) + 1;
1393530d68baSNigel Croxon     while (p1 != str) {
1394530d68baSNigel Croxon 
1395530d68baSNigel Croxon         c -= 1;
1396530d68baSNigel Croxon         if (!c) {
1397530d68baSNigel Croxon             *(p2++) = ',';
1398530d68baSNigel Croxon             c = 3;
1399530d68baSNigel Croxon         }
1400530d68baSNigel Croxon 
1401530d68baSNigel Croxon         *(p2++) = *(--p1);
1402530d68baSNigel Croxon     }
1403530d68baSNigel Croxon     *p2 = 0;
1404530d68baSNigel Croxon }
1405530d68baSNigel Croxon 
1406530d68baSNigel Croxon VOID
FloatToString(IN CHAR16 * Buffer,IN BOOLEAN Comma,IN double v)1407b2c4db06SNigel Croxon FloatToString (
1408b2c4db06SNigel Croxon     IN CHAR16   *Buffer,
1409b2c4db06SNigel Croxon     IN BOOLEAN  Comma,
1410b2c4db06SNigel Croxon     IN double   v
1411b2c4db06SNigel Croxon     )
1412b2c4db06SNigel Croxon {
1413b2c4db06SNigel Croxon     /*
1414b2c4db06SNigel Croxon      * Integer part.
1415b2c4db06SNigel Croxon      */
1416b2c4db06SNigel Croxon     INTN i = (INTN)v;
1417b2c4db06SNigel Croxon     ValueToString(Buffer, Comma, i);
1418b2c4db06SNigel Croxon 
1419b2c4db06SNigel Croxon 
1420b2c4db06SNigel Croxon     /*
1421b2c4db06SNigel Croxon      * Decimal point.
1422b2c4db06SNigel Croxon      */
1423b2c4db06SNigel Croxon     UINTN x = StrLen(Buffer);
1424b2c4db06SNigel Croxon     Buffer[x] = L'.';
142544d9ae19SNigel Croxon     x++;
1426b2c4db06SNigel Croxon 
1427b2c4db06SNigel Croxon 
1428b2c4db06SNigel Croxon     /*
142944d9ae19SNigel Croxon      * Keep fractional part.
1430b2c4db06SNigel Croxon      */
143193ef2655SNigel Croxon     float f = (float)(v - i);
1432b2c4db06SNigel Croxon     if (f < 0) f = -f;
143344d9ae19SNigel Croxon 
143444d9ae19SNigel Croxon 
143544d9ae19SNigel Croxon     /*
143644d9ae19SNigel Croxon      * Leading fractional zeroes.
143744d9ae19SNigel Croxon      */
143844d9ae19SNigel Croxon     f *= 10.0;
143944d9ae19SNigel Croxon     while (   (f != 0)
144044d9ae19SNigel Croxon            && ((INTN)f == 0))
144144d9ae19SNigel Croxon     {
144244d9ae19SNigel Croxon       Buffer[x] = L'0';
144344d9ae19SNigel Croxon       x++;
144444d9ae19SNigel Croxon       f *= 10.0;
144544d9ae19SNigel Croxon     }
144644d9ae19SNigel Croxon 
144744d9ae19SNigel Croxon 
144844d9ae19SNigel Croxon     /*
144944d9ae19SNigel Croxon      * Fractional digits.
145044d9ae19SNigel Croxon      */
1451b2c4db06SNigel Croxon     while ((float)(INTN)f != f)
1452b2c4db06SNigel Croxon     {
1453b2c4db06SNigel Croxon       f *= 10;
1454b2c4db06SNigel Croxon     }
145544d9ae19SNigel Croxon     ValueToString(Buffer + x, FALSE, (INTN)f);
1456b2c4db06SNigel Croxon     return;
1457b2c4db06SNigel Croxon }
1458b2c4db06SNigel Croxon 
1459b2c4db06SNigel Croxon VOID
TimeToString(OUT CHAR16 * Buffer,IN EFI_TIME * Time)1460530d68baSNigel Croxon TimeToString (
1461530d68baSNigel Croxon     OUT CHAR16      *Buffer,
1462530d68baSNigel Croxon     IN EFI_TIME     *Time
1463530d68baSNigel Croxon     )
1464530d68baSNigel Croxon {
1465530d68baSNigel Croxon     UINTN       Hour, Year;
1466530d68baSNigel Croxon     CHAR16      AmPm;
1467530d68baSNigel Croxon 
1468530d68baSNigel Croxon     AmPm = 'a';
1469530d68baSNigel Croxon     Hour = Time->Hour;
1470530d68baSNigel Croxon     if (Time->Hour == 0) {
1471530d68baSNigel Croxon         Hour = 12;
1472530d68baSNigel Croxon     } else if (Time->Hour >= 12) {
1473530d68baSNigel Croxon         AmPm = 'p';
1474530d68baSNigel Croxon         if (Time->Hour >= 13) {
1475530d68baSNigel Croxon             Hour -= 12;
1476530d68baSNigel Croxon         }
1477530d68baSNigel Croxon     }
1478530d68baSNigel Croxon 
1479530d68baSNigel Croxon     Year = Time->Year % 100;
1480530d68baSNigel Croxon 
1481530d68baSNigel Croxon     // bugbug: for now just print it any old way
1482b39be0d5SPete Batard     UnicodeSPrint (Buffer, 0, L"%02d/%02d/%02d  %02d:%02d%c",
1483530d68baSNigel Croxon         Time->Month,
1484530d68baSNigel Croxon         Time->Day,
1485530d68baSNigel Croxon         Year,
1486530d68baSNigel Croxon         Hour,
1487530d68baSNigel Croxon         Time->Minute,
1488530d68baSNigel Croxon         AmPm
1489530d68baSNigel Croxon         );
1490530d68baSNigel Croxon }
1491530d68baSNigel Croxon 
1492530d68baSNigel Croxon 
1493530d68baSNigel Croxon 
1494530d68baSNigel Croxon 
1495530d68baSNigel Croxon VOID
DumpHex(IN UINTN Indent,IN UINTN Offset,IN UINTN DataSize,IN VOID * UserData)1496530d68baSNigel Croxon DumpHex (
1497530d68baSNigel Croxon     IN UINTN        Indent,
1498530d68baSNigel Croxon     IN UINTN        Offset,
1499530d68baSNigel Croxon     IN UINTN        DataSize,
1500530d68baSNigel Croxon     IN VOID         *UserData
1501530d68baSNigel Croxon     )
1502530d68baSNigel Croxon {
1503530d68baSNigel Croxon     CHAR8           *Data, Val[50], Str[20], c;
1504530d68baSNigel Croxon     UINTN           Size, Index;
1505530d68baSNigel Croxon 
1506530d68baSNigel Croxon     UINTN           ScreenCount;
1507530d68baSNigel Croxon     UINTN           TempColumn;
1508530d68baSNigel Croxon     UINTN           ScreenSize;
1509530d68baSNigel Croxon     CHAR16          ReturnStr[1];
1510530d68baSNigel Croxon 
1511530d68baSNigel Croxon 
1512530d68baSNigel Croxon     uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
1513530d68baSNigel Croxon     ScreenCount = 0;
1514530d68baSNigel Croxon     ScreenSize -= 2;
1515530d68baSNigel Croxon 
1516530d68baSNigel Croxon     Data = UserData;
1517530d68baSNigel Croxon     while (DataSize) {
1518530d68baSNigel Croxon         Size = 16;
1519530d68baSNigel Croxon         if (Size > DataSize) {
1520530d68baSNigel Croxon             Size = DataSize;
1521530d68baSNigel Croxon         }
1522530d68baSNigel Croxon 
1523530d68baSNigel Croxon         for (Index=0; Index < Size; Index += 1) {
1524530d68baSNigel Croxon             c = Data[Index];
1525530d68baSNigel Croxon             Val[Index*3+0] = Hex[c>>4];
1526530d68baSNigel Croxon             Val[Index*3+1] = Hex[c&0xF];
1527530d68baSNigel Croxon             Val[Index*3+2] = (Index == 7)?'-':' ';
1528530d68baSNigel Croxon             Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
1529530d68baSNigel Croxon         }
1530530d68baSNigel Croxon 
1531530d68baSNigel Croxon         Val[Index*3] = 0;
1532530d68baSNigel Croxon         Str[Index] = 0;
1533530d68baSNigel Croxon         Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
1534530d68baSNigel Croxon 
1535530d68baSNigel Croxon         Data += Size;
1536530d68baSNigel Croxon         Offset += Size;
1537530d68baSNigel Croxon         DataSize -= Size;
1538530d68baSNigel Croxon 
1539530d68baSNigel Croxon         ScreenCount++;
1540530d68baSNigel Croxon         if (ScreenCount >= ScreenSize && ScreenSize != 0) {
1541530d68baSNigel Croxon             //
1542530d68baSNigel Croxon             // If ScreenSize == 0 we have the console redirected so don't
1543530d68baSNigel Croxon             //  block updates
1544530d68baSNigel Croxon             //
1545530d68baSNigel Croxon             ScreenCount = 0;
1546530d68baSNigel Croxon             Print (L"Press Enter to continue :");
1547530d68baSNigel Croxon             Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
1548530d68baSNigel Croxon             Print (L"\n");
1549530d68baSNigel Croxon         }
1550530d68baSNigel Croxon 
1551530d68baSNigel Croxon     }
1552530d68baSNigel Croxon }
1553