gnu-efi/gnu-efi-3.0/lib/print.c
Nigel Croxon 644898eabc The prototype of DbgPrint() is incorrect, at the end of "inc/efidebug.h".
Consequently, when your program calls DbgPrint() via the DEBUG() macro,
it fails to set up the stack correctly (it does not pass the arguments
through the ellipsis (...) according to the EFIAPI calling convention).
However, va_start() inside DbgPrint() *assumes* that stack.

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Nigel Croxon <nigel.croxon@hp.com>
2014-05-14 09:12:52 -04:00

1367 lines
26 KiB
C

/*++
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 EFIAPI
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");
}
}
}