0,0 → 1,1301 |
/*++ |
|
Copyright (c) 1998 Intel Corporation |
|
Module Name: |
|
print.c |
|
Abstract: |
|
|
|
|
Revision History |
|
--*/ |
|
#include "lib.h" |
#include "efistdarg.h" // !!! |
|
// |
// Declare runtime functions |
// |
|
#ifdef RUNTIME_CODE |
#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 |
|
// |
// |
// |
|
|
#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 (*Output)(VOID *context, CHAR16 *str); |
INTN (*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 |
_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 |
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 (*)(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 |
_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) { |
DbgOut->OutputString (DbgOut, Buffer); |
} |
|
return 0; |
} |
|
INTN |
_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 |
_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 (*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 |
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 |
|
--*/ |
{ |
POOL_PRINT spc; |
va_list args; |
|
|
va_start (args, fmt); |
spc.str = Str; |
spc.maxlen = StrSize / sizeof(CHAR16) - 1; |
spc.len = 0; |
|
_PoolCatPrint (fmt, args, &spc, _SPrint); |
va_end (args); |
return spc.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 (*)(VOID *, CHAR16 *)) Out->OutputString; |
ps.SetAttr = (INTN (*)(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) { |
Out->SetCursorPosition(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; |
ps->Output(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) { |
ps->SetAttr (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, UINTN) |
); |
|
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, UINTN) |
); |
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]; |
|
|
ST->ConOut->QueryMode (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"); |
} |
|
} |
} |