aboutsummaryrefslogtreecommitdiff
path: root/gnu-efi/gnu-efi-3.0/lib/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu-efi/gnu-efi-3.0/lib/print.c')
-rw-r--r--gnu-efi/gnu-efi-3.0/lib/print.c1366
1 files changed, 1366 insertions, 0 deletions
diff --git a/gnu-efi/gnu-efi-3.0/lib/print.c b/gnu-efi/gnu-efi-3.0/lib/print.c
new file mode 100644
index 0000000..eaea90c
--- /dev/null
+++ b/gnu-efi/gnu-efi-3.0/lib/print.c
@@ -0,0 +1,1366 @@
+/*++
+
+Copyright (c) 1998 Intel Corporation
+
+Module Name:
+
+ print.c
+
+Abstract:
+
+
+
+
+Revision History
+
+--*/
+
+#include "lib.h"
+#include "efistdarg.h" // !!!
+
+//
+// Declare runtime functions
+//
+
+#ifdef RUNTIME_CODE
+#ifndef __GNUC__
+#pragma RUNTIME_CODE(DbgPrint)
+
+// For debugging..
+
+/*
+#pragma RUNTIME_CODE(_Print)
+#pragma RUNTIME_CODE(PFLUSH)
+#pragma RUNTIME_CODE(PSETATTR)
+#pragma RUNTIME_CODE(PPUTC)
+#pragma RUNTIME_CODE(PGETC)
+#pragma RUNTIME_CODE(PITEM)
+#pragma RUNTIME_CODE(ValueToHex)
+#pragma RUNTIME_CODE(ValueToString)
+#pragma RUNTIME_CODE(TimeToString)
+*/
+
+#endif /* !defined(__GNUC__) */
+#endif
+
+//
+//
+//
+
+
+#define PRINT_STRING_LEN 200
+#define PRINT_ITEM_BUFFER_LEN 100
+
+typedef struct {
+ BOOLEAN Ascii;
+ UINTN Index;
+ union {
+ CHAR16 *pw;
+ CHAR8 *pc;
+ } un;
+} POINTER;
+
+#define pw un.pw
+#define pc un.pc
+
+typedef struct _pitem {
+
+ POINTER Item;
+ CHAR16 Scratch[PRINT_ITEM_BUFFER_LEN];
+ UINTN Width;
+ UINTN FieldWidth;
+ UINTN *WidthParse;
+ CHAR16 Pad;
+ BOOLEAN PadBefore;
+ BOOLEAN Comma;
+ BOOLEAN Long;
+} PRINT_ITEM;
+
+
+typedef struct _pstate {
+ // Input
+ POINTER fmt;
+ va_list args;
+
+ // Output
+ CHAR16 *Buffer;
+ CHAR16 *End;
+ CHAR16 *Pos;
+ UINTN Len;
+
+ UINTN Attr;
+ UINTN RestoreAttr;
+
+ UINTN AttrNorm;
+ UINTN AttrHighlight;
+ UINTN AttrError;
+
+ INTN EFIAPI (*Output)(VOID *context, CHAR16 *str);
+ INTN EFIAPI (*SetAttr)(VOID *context, UINTN attr);
+ VOID *Context;
+
+ // Current item being formatted
+ struct _pitem *Item;
+} PRINT_STATE;
+
+//
+// Internal fucntions
+//
+
+STATIC
+UINTN
+_Print (
+ IN PRINT_STATE *ps
+ );
+
+STATIC
+UINTN
+_IPrint (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
+ IN CHAR16 *fmt,
+ IN CHAR8 *fmta,
+ IN va_list args
+ );
+
+STATIC
+INTN EFIAPI
+_DbgOut (
+ IN VOID *Context,
+ IN CHAR16 *Buffer
+ );
+
+STATIC
+VOID
+PFLUSH (
+ IN OUT PRINT_STATE *ps
+ );
+
+STATIC
+VOID
+PPUTC (
+ IN OUT PRINT_STATE *ps,
+ IN CHAR16 c
+ );
+
+STATIC
+VOID
+PITEM (
+ IN OUT PRINT_STATE *ps
+ );
+
+STATIC
+CHAR16
+PGETC (
+ IN POINTER *p
+ );
+
+STATIC
+VOID
+PSETATTR (
+ IN OUT PRINT_STATE *ps,
+ IN UINTN Attr
+ );
+
+//
+//
+//
+
+INTN EFIAPI
+_SPrint (
+ IN VOID *Context,
+ IN CHAR16 *Buffer
+ );
+
+INTN EFIAPI
+_PoolPrint (
+ IN VOID *Context,
+ IN CHAR16 *Buffer
+ );
+
+INTN
+DbgPrint (
+ IN INTN mask,
+ IN CHAR8 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the default StandardError console
+
+Arguments:
+
+ mask - Bit mask of debug string. If a bit is set in the
+ mask that is also set in EFIDebug the string is
+ printed; otherwise, the string is not printed
+
+ fmt - Format string
+
+Returns:
+
+ Length of string printed to the StandardError console
+
+--*/
+{
+ SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
+ PRINT_STATE ps;
+ va_list args;
+ UINTN back;
+ UINTN attr;
+ UINTN SavedAttribute;
+
+
+ if (!(EFIDebug & mask)) {
+ return 0;
+ }
+
+ va_start (args, fmt);
+ ZeroMem (&ps, sizeof(ps));
+
+ ps.Output = _DbgOut;
+ ps.fmt.Ascii = TRUE;
+ ps.fmt.pc = fmt;
+ va_copy(ps.args, args);
+ ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED);
+
+ DbgOut = LibRuntimeDebugOut;
+
+ if (!DbgOut) {
+ DbgOut = ST->StdErr;
+ }
+
+ if (DbgOut) {
+ ps.Attr = DbgOut->Mode->Attribute;
+ ps.Context = DbgOut;
+ ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN)) DbgOut->SetAttribute;
+ }
+
+ SavedAttribute = ps.Attr;
+
+ back = (ps.Attr >> 4) & 0xf;
+ ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
+ ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
+ ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
+
+ attr = ps.AttrNorm;
+
+ if (mask & D_WARN) {
+ attr = ps.AttrHighlight;
+ }
+
+ if (mask & D_ERROR) {
+ attr = ps.AttrError;
+ }
+
+ if (ps.SetAttr) {
+ ps.Attr = attr;
+ ps.SetAttr (ps.Context, attr);
+ }
+
+ _Print (&ps);
+
+ va_end (ps.args);
+ va_end (args);
+
+ //
+ // Restore original attributes
+ //
+
+ if (ps.SetAttr) {
+ ps.SetAttr (ps.Context, SavedAttribute);
+ }
+
+ return 0;
+}
+
+STATIC
+INTN
+IsLocalPrint(void *func)
+{
+ if (func == _DbgOut || func == _SPrint || func == _PoolPrint)
+ return 1;
+ return 0;
+}
+
+STATIC
+INTN EFIAPI
+_DbgOut (
+ IN VOID *Context,
+ IN CHAR16 *Buffer
+ )
+// Append string worker for DbgPrint
+{
+ SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
+
+ DbgOut = Context;
+// if (!DbgOut && ST && ST->ConOut) {
+// DbgOut = ST->ConOut;
+// }
+
+ if (DbgOut) {
+ if (IsLocalPrint(DbgOut->OutputString))
+ DbgOut->OutputString(DbgOut, Buffer);
+ else
+ uefi_call_wrapper(DbgOut->OutputString, 2, DbgOut, Buffer);
+ }
+
+ return 0;
+}
+
+INTN EFIAPI
+_SPrint (
+ IN VOID *Context,
+ IN CHAR16 *Buffer
+ )
+// Append string worker for SPrint, PoolPrint and CatPrint
+{
+ UINTN len;
+ POOL_PRINT *spc;
+
+ spc = Context;
+ len = StrLen(Buffer);
+
+ //
+ // Is the string is over the max truncate it
+ //
+
+ if (spc->len + len > spc->maxlen) {
+ len = spc->maxlen - spc->len;
+ }
+
+ //
+ // Append the new text
+ //
+
+ CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16));
+ spc->len += len;
+
+ //
+ // Null terminate it
+ //
+
+ if (spc->len < spc->maxlen) {
+ spc->str[spc->len] = 0;
+ } else if (spc->maxlen) {
+ spc->str[spc->maxlen-1] = 0;
+ }
+
+ return 0;
+}
+
+
+INTN EFIAPI
+_PoolPrint (
+ IN VOID *Context,
+ IN CHAR16 *Buffer
+ )
+// Append string worker for PoolPrint and CatPrint
+{
+ UINTN newlen;
+ POOL_PRINT *spc;
+
+ spc = Context;
+ newlen = spc->len + StrLen(Buffer) + 1;
+
+ //
+ // Is the string is over the max, grow the buffer
+ //
+
+ if (newlen > spc->maxlen) {
+
+ //
+ // Grow the pool buffer
+ //
+
+ newlen += PRINT_STRING_LEN;
+ spc->maxlen = newlen;
+ spc->str = ReallocatePool (
+ spc->str,
+ spc->len * sizeof(CHAR16),
+ spc->maxlen * sizeof(CHAR16)
+ );
+
+ if (!spc->str) {
+ spc->len = 0;
+ spc->maxlen = 0;
+ }
+ }
+
+ //
+ // Append the new text
+ //
+
+ return _SPrint (Context, Buffer);
+}
+
+
+
+VOID
+_PoolCatPrint (
+ IN CHAR16 *fmt,
+ IN va_list args,
+ IN OUT POOL_PRINT *spc,
+ IN INTN EFIAPI (*Output)(VOID *context, CHAR16 *str)
+ )
+// Dispath function for SPrint, PoolPrint, and CatPrint
+{
+ PRINT_STATE ps;
+
+ ZeroMem (&ps, sizeof(ps));
+ ps.Output = Output;
+ ps.Context = spc;
+ ps.fmt.pw = fmt;
+ va_copy(ps.args, args);
+ _Print (&ps);
+ va_end(ps.args);
+}
+
+
+
+UINTN
+VSPrint (
+ OUT CHAR16 *Str,
+ IN UINTN StrSize,
+ IN CHAR16 *fmt,
+ va_list args
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to a buffer using a va_list
+
+Arguments:
+
+ Str - Output buffer to print the formatted string into
+
+ StrSize - Size of Str. String is truncated to this size.
+ A size of 0 means there is no limit
+
+ fmt - The format string
+
+ args - va_list
+
+
+Returns:
+
+ String length returned in buffer
+
+--*/
+{
+ POOL_PRINT spc;
+
+ spc.str = Str;
+ spc.maxlen = StrSize / sizeof(CHAR16) - 1;
+ spc.len = 0;
+
+ _PoolCatPrint (fmt, args, &spc, _SPrint);
+
+ return spc.len;
+}
+
+UINTN
+SPrint (
+ OUT CHAR16 *Str,
+ IN UINTN StrSize,
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to a buffer
+
+Arguments:
+
+ Str - Output buffer to print the formatted string into
+
+ StrSize - Size of Str. String is truncated to this size.
+ A size of 0 means there is no limit
+
+ fmt - The format string
+
+Returns:
+
+ String length returned in buffer
+
+--*/
+{
+ va_list args;
+ UINTN len;
+
+ va_start (args, fmt);
+ len = VSPrint(Str, StrSize, fmt, args);
+ va_end (args);
+
+ return len;
+}
+
+
+CHAR16 *
+PoolPrint (
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to allocated pool. The caller
+ must free the resulting buffer.
+
+Arguments:
+
+ fmt - The format string
+
+Returns:
+
+ Allocated buffer with the formatted string printed in it.
+ The caller must free the allocated buffer. The buffer
+ allocation is not packed.
+
+--*/
+{
+ POOL_PRINT spc;
+ va_list args;
+
+ ZeroMem (&spc, sizeof(spc));
+ va_start (args, fmt);
+ _PoolCatPrint (fmt, args, &spc, _PoolPrint);
+ va_end (args);
+ return spc.str;
+}
+
+
+
+CHAR16 *
+CatPrint (
+ IN OUT POOL_PRINT *Str,
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Concatenates a formatted unicode string to allocated pool.
+ The caller must free the resulting buffer.
+
+Arguments:
+
+ Str - Tracks the allocated pool, size in use, and
+ amount of pool allocated.
+
+ fmt - The format string
+
+Returns:
+
+ Allocated buffer with the formatted string printed in it.
+ The caller must free the allocated buffer. The buffer
+ allocation is not packed.
+
+--*/
+{
+ va_list args;
+
+ va_start (args, fmt);
+ _PoolCatPrint (fmt, args, Str, _PoolPrint);
+ va_end (args);
+ return Str->str;
+}
+
+
+
+UINTN
+Print (
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the default console
+
+Arguments:
+
+ fmt - Format string
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ va_list args;
+ UINTN back;
+
+ va_start (args, fmt);
+ back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
+ va_end (args);
+ return back;
+}
+
+UINTN
+VPrint (
+ IN CHAR16 *fmt,
+ va_list args
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the default console using a va_list
+
+Arguments:
+
+ fmt - Format string
+ args - va_list
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
+}
+
+
+UINTN
+PrintAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the default console, at
+ the supplied cursor position
+
+Arguments:
+
+ Column, Row - The cursor position to print the string at
+
+ fmt - Format string
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ va_list args;
+ UINTN back;
+
+ va_start (args, fmt);
+ back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
+ va_end (args);
+ return back;
+}
+
+
+UINTN
+IPrint (
+ IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the specified console
+
+Arguments:
+
+ Out - The console to print the string too
+
+ fmt - Format string
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ va_list args;
+ UINTN back;
+
+ va_start (args, fmt);
+ back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
+ va_end (args);
+ return back;
+}
+
+
+UINTN
+IPrintAt (
+ IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ Prints a formatted unicode string to the specified console, at
+ the supplied cursor position
+
+Arguments:
+
+ Out - The console to print the string too
+
+ Column, Row - The cursor position to print the string at
+
+ fmt - Format string
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+{
+ va_list args;
+ UINTN back;
+
+ va_start (args, fmt);
+ back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
+ va_end (args);
+ return back;
+}
+
+
+UINTN
+_IPrint (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
+ IN CHAR16 *fmt,
+ IN CHAR8 *fmta,
+ IN va_list args
+ )
+// Display string worker for: Print, PrintAt, IPrint, IPrintAt
+{
+ PRINT_STATE ps;
+ UINTN back;
+
+ ZeroMem (&ps, sizeof(ps));
+ ps.Context = Out;
+ ps.Output = (INTN EFIAPI (*)(VOID *, CHAR16 *)) Out->OutputString;
+ ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN)) Out->SetAttribute;
+ ps.Attr = Out->Mode->Attribute;
+
+ back = (ps.Attr >> 4) & 0xF;
+ ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
+ ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
+ ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
+
+ if (fmt) {
+ ps.fmt.pw = fmt;
+ } else {
+ ps.fmt.Ascii = TRUE;
+ ps.fmt.pc = fmta;
+ }
+
+ va_copy(ps.args, args);
+
+ if (Column != (UINTN) -1) {
+ uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row);
+ }
+
+ back = _Print (&ps);
+ va_end(ps.args);
+ return back;
+}
+
+
+UINTN
+APrint (
+ IN CHAR8 *fmt,
+ ...
+ )
+/*++
+
+Routine Description:
+
+ For those whom really can't deal with unicode, a print
+ function that takes an ascii format string
+
+Arguments:
+
+ fmt - ascii format string
+
+Returns:
+
+ Length of string printed to the console
+
+--*/
+
+{
+ va_list args;
+ UINTN back;
+
+ va_start (args, fmt);
+ back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
+ va_end (args);
+ return back;
+}
+
+
+STATIC
+VOID
+PFLUSH (
+ IN OUT PRINT_STATE *ps
+ )
+{
+ *ps->Pos = 0;
+ if (IsLocalPrint(ps->Output))
+ ps->Output(ps->Context, ps->Buffer);
+ else
+ uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
+ ps->Pos = ps->Buffer;
+}
+
+STATIC
+VOID
+PSETATTR (
+ IN OUT PRINT_STATE *ps,
+ IN UINTN Attr
+ )
+{
+ PFLUSH (ps);
+
+ ps->RestoreAttr = ps->Attr;
+ if (ps->SetAttr) {
+ uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
+ }
+
+ ps->Attr = Attr;
+}
+
+STATIC
+VOID
+PPUTC (
+ IN OUT PRINT_STATE *ps,
+ IN CHAR16 c
+ )
+{
+ // if this is a newline, add a carraige return
+ if (c == '\n') {
+ PPUTC (ps, '\r');
+ }
+
+ *ps->Pos = c;
+ ps->Pos += 1;
+ ps->Len += 1;
+
+ // if at the end of the buffer, flush it
+ if (ps->Pos >= ps->End) {
+ PFLUSH(ps);
+ }
+}
+
+
+STATIC
+CHAR16
+PGETC (
+ IN POINTER *p
+ )
+{
+ CHAR16 c;
+
+ c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
+ p->Index += 1;
+
+ return c;
+}
+
+
+STATIC
+VOID
+PITEM (
+ IN OUT PRINT_STATE *ps
+ )
+{
+ UINTN Len, i;
+ PRINT_ITEM *Item;
+ CHAR16 c;
+
+ // Get the length of the item
+ Item = ps->Item;
+ Item->Item.Index = 0;
+ while (Item->Item.Index < Item->FieldWidth) {
+ c = PGETC(&Item->Item);
+ if (!c) {
+ Item->Item.Index -= 1;
+ break;
+ }
+ }
+ Len = Item->Item.Index;
+
+ // if there is no item field width, use the items width
+ if (Item->FieldWidth == (UINTN) -1) {
+ Item->FieldWidth = Len;
+ }
+
+ // if item is larger then width, update width
+ if (Len > Item->Width) {
+ Item->Width = Len;
+ }
+
+
+ // if pad field before, add pad char
+ if (Item->PadBefore) {
+ for (i=Item->Width; i < Item->FieldWidth; i+=1) {
+ PPUTC (ps, ' ');
+ }
+ }
+
+ // pad item
+ for (i=Len; i < Item->Width; i++) {
+ PPUTC (ps, Item->Pad);
+ }
+
+ // add the item
+ Item->Item.Index=0;
+ while (Item->Item.Index < Len) {
+ PPUTC (ps, PGETC(&Item->Item));
+ }
+
+ // If pad at the end, add pad char
+ if (!Item->PadBefore) {
+ for (i=Item->Width; i < Item->FieldWidth; i+=1) {
+ PPUTC (ps, ' ');
+ }
+ }
+}
+
+
+STATIC
+UINTN
+_Print (
+ IN PRINT_STATE *ps
+ )
+/*++
+
+Routine Description:
+
+ %w.lF - w = width
+ l = field width
+ F = format of arg
+
+ Args F:
+ 0 - pad with zeros
+ - - justify on left (default is on right)
+ , - add comma's to field
+ * - width provided on stack
+ n - Set output attribute to normal (for this field only)
+ h - Set output attribute to highlight (for this field only)
+ e - Set output attribute to error (for this field only)
+ l - Value is 64 bits
+
+ a - ascii string
+ s - unicode string
+ X - fixed 8 byte value in hex
+ x - hex value
+ d - value as decimal
+ c - Unicode char
+ t - EFI time structure
+ g - Pointer to GUID
+ r - EFI status code (result code)
+
+ N - Set output attribute to normal
+ H - Set output attribute to highlight
+ E - Set output attribute to error
+ % - Print a %
+
+Arguments:
+
+ SystemTable - The system table
+
+Returns:
+
+ Number of charactors written
+
+--*/
+{
+ CHAR16 c;
+ UINTN Attr;
+ PRINT_ITEM Item;
+ CHAR16 Buffer[PRINT_STRING_LEN];
+
+ ps->Len = 0;
+ ps->Buffer = Buffer;
+ ps->Pos = Buffer;
+ ps->End = Buffer + PRINT_STRING_LEN - 1;
+ ps->Item = &Item;
+
+ ps->fmt.Index = 0;
+ while ((c = PGETC(&ps->fmt))) {
+
+ if (c != '%') {
+ PPUTC ( ps, c );
+ continue;
+ }
+
+ // setup for new item
+ Item.FieldWidth = (UINTN) -1;
+ Item.Width = 0;
+ Item.WidthParse = &Item.Width;
+ Item.Pad = ' ';
+ Item.PadBefore = TRUE;
+ Item.Comma = FALSE;
+ Item.Long = FALSE;
+ Item.Item.Ascii = FALSE;
+ Item.Item.pw = NULL;
+ ps->RestoreAttr = 0;
+ Attr = 0;
+
+ while ((c = PGETC(&ps->fmt))) {
+
+ switch (c) {
+
+ case '%':
+ //
+ // %% -> %
+ //
+ Item.Item.pw = Item.Scratch;
+ Item.Item.pw[0] = '%';
+ Item.Item.pw[1] = 0;
+ break;
+
+ case '0':
+ Item.Pad = '0';
+ break;
+
+ case '-':
+ Item.PadBefore = FALSE;
+ break;
+
+ case ',':
+ Item.Comma = TRUE;
+ break;
+
+ case '.':
+ Item.WidthParse = &Item.FieldWidth;
+ break;
+
+ case '*':
+ *Item.WidthParse = va_arg(ps->args, UINTN);
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ *Item.WidthParse = 0;
+ do {
+ *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
+ c = PGETC(&ps->fmt);
+ } while (c >= '0' && c <= '9') ;
+ ps->fmt.Index -= 1;
+ break;
+
+ case 'a':
+ Item.Item.pc = va_arg(ps->args, CHAR8 *);
+ Item.Item.Ascii = TRUE;
+ if (!Item.Item.pc) {
+ Item.Item.pc = (CHAR8 *)"(null)";
+ }
+ break;
+
+ case 's':
+ Item.Item.pw = va_arg(ps->args, CHAR16 *);
+ if (!Item.Item.pw) {
+ Item.Item.pw = L"(null)";
+ }
+ break;
+
+ case 'c':
+ Item.Item.pw = Item.Scratch;
+ Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
+ Item.Item.pw[1] = 0;
+ break;
+
+ case 'l':
+ Item.Long = TRUE;
+ break;
+
+ case 'X':
+ Item.Width = Item.Long ? 16 : 8;
+ Item.Pad = '0';
+ case 'x':
+ Item.Item.pw = Item.Scratch;
+ ValueToHex (
+ Item.Item.pw,
+ Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
+ );
+
+ break;
+
+
+ case 'g':
+ Item.Item.pw = Item.Scratch;
+ GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
+ break;
+
+ case 'd':
+ Item.Item.pw = Item.Scratch;
+ ValueToString (
+ Item.Item.pw,
+ Item.Comma,
+ Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
+ );
+ break
+ ;
+ case 't':
+ Item.Item.pw = Item.Scratch;
+ TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
+ break;
+
+ case 'r':
+ Item.Item.pw = Item.Scratch;
+ StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
+ break;
+
+ case 'n':
+ PSETATTR(ps, ps->AttrNorm);
+ break;
+
+ case 'h':
+ PSETATTR(ps, ps->AttrHighlight);
+ break;
+
+ case 'e':
+ PSETATTR(ps, ps->AttrError);
+ break;
+
+ case 'N':
+ Attr = ps->AttrNorm;
+ break;
+
+ case 'H':
+ Attr = ps->AttrHighlight;
+ break;
+
+ case 'E':
+ Attr = ps->AttrError;
+ break;
+
+ default:
+ Item.Item.pw = Item.Scratch;
+ Item.Item.pw[0] = '?';
+ Item.Item.pw[1] = 0;
+ break;
+ }
+
+ // if we have an Item
+ if (Item.Item.pw) {
+ PITEM (ps);
+ break;
+ }
+
+ // if we have an Attr set
+ if (Attr) {
+ PSETATTR(ps, Attr);
+ ps->RestoreAttr = 0;
+ break;
+ }
+ }
+
+ if (ps->RestoreAttr) {
+ PSETATTR(ps, ps->RestoreAttr);
+ }
+ }
+
+ // Flush buffer
+ PFLUSH (ps);
+ return ps->Len;
+}
+
+STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
+ '8','9','A','B','C','D','E','F'};
+
+VOID
+ValueToHex (
+ IN CHAR16 *Buffer,
+ IN UINT64 v
+ )
+{
+ CHAR8 str[30], *p1;
+ CHAR16 *p2;
+
+ if (!v) {
+ Buffer[0] = '0';
+ Buffer[1] = 0;
+ return ;
+ }
+
+ p1 = str;
+ p2 = Buffer;
+
+ while (v) {
+ *(p1++) = Hex[v & 0xf];
+ v = RShiftU64 (v, 4);
+ }
+
+ while (p1 != str) {
+ *(p2++) = *(--p1);
+ }
+ *p2 = 0;
+}
+
+
+VOID
+ValueToString (
+ IN CHAR16 *Buffer,
+ IN BOOLEAN Comma,
+ IN INT64 v
+ )
+{
+ STATIC CHAR8 ca[] = { 3, 1, 2 };
+ CHAR8 str[40], *p1;
+ CHAR16 *p2;
+ UINTN c, r;
+
+ if (!v) {
+ Buffer[0] = '0';
+ Buffer[1] = 0;
+ return ;
+ }
+
+ p1 = str;
+ p2 = Buffer;
+
+ if (v < 0) {
+ *(p2++) = '-';
+ v = -v;
+ }
+
+ while (v) {
+ v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
+ *(p1++) = (CHAR8)r + '0';
+ }
+
+ c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
+ while (p1 != str) {
+
+ c -= 1;
+ if (!c) {
+ *(p2++) = ',';
+ c = 3;
+ }
+
+ *(p2++) = *(--p1);
+ }
+ *p2 = 0;
+}
+
+VOID
+TimeToString (
+ OUT CHAR16 *Buffer,
+ IN EFI_TIME *Time
+ )
+{
+ UINTN Hour, Year;
+ CHAR16 AmPm;
+
+ AmPm = 'a';
+ Hour = Time->Hour;
+ if (Time->Hour == 0) {
+ Hour = 12;
+ } else if (Time->Hour >= 12) {
+ AmPm = 'p';
+ if (Time->Hour >= 13) {
+ Hour -= 12;
+ }
+ }
+
+ Year = Time->Year % 100;
+
+ // bugbug: for now just print it any old way
+ SPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c",
+ Time->Month,
+ Time->Day,
+ Year,
+ Hour,
+ Time->Minute,
+ AmPm
+ );
+}
+
+
+
+
+VOID
+DumpHex (
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ )
+{
+ CHAR8 *Data, Val[50], Str[20], c;
+ UINTN Size, Index;
+
+ UINTN ScreenCount;
+ UINTN TempColumn;
+ UINTN ScreenSize;
+ CHAR16 ReturnStr[1];
+
+
+ uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
+ ScreenCount = 0;
+ ScreenSize -= 2;
+
+ Data = UserData;
+ while (DataSize) {
+ Size = 16;
+ if (Size > DataSize) {
+ Size = DataSize;
+ }
+
+ for (Index=0; Index < Size; Index += 1) {
+ c = Data[Index];
+ Val[Index*3+0] = Hex[c>>4];
+ Val[Index*3+1] = Hex[c&0xF];
+ Val[Index*3+2] = (Index == 7)?'-':' ';
+ Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
+ }
+
+ Val[Index*3] = 0;
+ Str[Index] = 0;
+ Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
+
+ Data += Size;
+ Offset += Size;
+ DataSize -= Size;
+
+ ScreenCount++;
+ if (ScreenCount >= ScreenSize && ScreenSize != 0) {
+ //
+ // If ScreenSize == 0 we have the console redirected so don't
+ // block updates
+ //
+ ScreenCount = 0;
+ Print (L"Press Enter to continue :");
+ Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
+ Print (L"\n");
+ }
+
+ }
+}