1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552 |
- /*++
- 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 {
- CONST CHAR16 *pw;
- CONST 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 CONST CHAR16 *fmt,
- IN CONST 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 CONST 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;
- uefi_call_wrapper(ps.SetAttr, 2, ps.Context, attr);
- }
- _Print (&ps);
- va_end (ps.args);
- va_end (args);
- //
- // Restore original attributes
- //
- if (ps.SetAttr) {
- uefi_call_wrapper(ps.SetAttr, 2, 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 UnicodeSPrint, 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] = 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 CONST CHAR16 *fmt,
- IN va_list args,
- IN OUT POOL_PRINT *spc,
- IN INTN (EFIAPI *Output)(VOID *context, CHAR16 *str)
- )
- // Dispatch function for UnicodeSPrint, 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
- UnicodeVSPrint (
- OUT CHAR16 *Str,
- IN UINTN StrSize,
- IN CONST 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
- UnicodeSPrint (
- OUT CHAR16 *Str,
- IN UINTN StrSize,
- IN CONST 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 = UnicodeVSPrint(Str, StrSize, fmt, args);
- va_end (args);
- return len;
- }
- CHAR16 *
- VPoolPrint (
- IN CONST CHAR16 *fmt,
- va_list args
- )
- /*++
- Routine Description:
- Prints a formatted unicode string to allocated pool using va_list argument.
- The caller must free the resulting buffer.
- Arguments:
- fmt - The format string
- args - The arguments in va_list form
- 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;
- ZeroMem (&spc, sizeof(spc));
- _PoolCatPrint (fmt, args, &spc, _PoolPrint);
- return spc.str;
- }
- CHAR16 *
- PoolPrint (
- IN CONST 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.
- --*/
- {
- va_list args;
- CHAR16 *pool;
- va_start (args, fmt);
- pool = VPoolPrint(fmt, args);
- va_end (args);
- return pool;
- }
- CHAR16 *
- CatPrint (
- IN OUT POOL_PRINT *Str,
- IN CONST 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 CONST 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 CONST 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 CONST 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 CONST 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 CONST 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 to
- 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, Out, fmt, NULL, args);
- va_end (args);
- return back;
- }
- 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
- )
- // 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
- AsciiPrint (
- IN CONST 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;
- }
- UINTN
- AsciiVSPrint (
- OUT CHAR8 *Str,
- IN UINTN StrSize,
- IN CONST CHAR8 *fmt,
- va_list args
- )
- /*++
- Routine Description:
- Prints a formatted ascii 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
- --*/
- // Use UnicodeVSPrint() and convert back to ASCII
- {
- CHAR16 *UnicodeStr, *UnicodeFmt;
- UINTN i, Len;
- UnicodeStr = AllocatePool(StrSize * sizeof(CHAR16));
- if (!UnicodeStr)
- return 0;
- UnicodeFmt = PoolPrint(L"%a", fmt);
- if (!UnicodeFmt) {
- FreePool(UnicodeStr);
- return 0;
- }
- Len = UnicodeVSPrint(UnicodeStr, StrSize, UnicodeFmt, args);
- FreePool(UnicodeFmt);
- // The strings are ASCII so just do a plain Unicode conversion
- for (i = 0; i < Len; i++)
- Str[i] = (CHAR8)UnicodeStr[i];
- Str[Len] = 0;
- FreePool(UnicodeStr);
- return Len;
- }
- 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 signed decimal
- u - value as unsigned decimal
- f - value as floating point
- c - Unicode char
- t - EFI time structure
- g - Pointer to GUID
- r - EFI status code (result code)
- D - pointer to Device Path with normal ending.
- 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.Scratch[0] = '%';
- Item.Scratch[1] = 0;
- Item.Item.pw = Item.Scratch;
- break;
- case ',':
- Item.Comma = TRUE;
- break;
- case '-':
- Item.PadBefore = FALSE;
- break;
- case '*':
- *Item.WidthParse = va_arg(ps->args, UINTN);
- break;
- case '.':
- Item.WidthParse = &Item.FieldWidth;
- break;
- case '0':
- Item.Pad = '0';
- 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 'c':
- Item.Scratch[0] = (CHAR16) va_arg(ps->args, UINTN);
- Item.Scratch[1] = 0;
- Item.Item.pw = Item.Scratch;
- break;
- case 'D':
- {
- EFI_DEVICE_PATH *dp = va_arg(ps->args, EFI_DEVICE_PATH *);
- CHAR16 *dpstr = DevicePathToStr(dp);
- StrnCpy(Item.Scratch, dpstr, PRINT_ITEM_BUFFER_LEN);
- Item.Scratch[PRINT_ITEM_BUFFER_LEN-1] = L'\0';
- FreePool(dpstr);
- Item.Item.pw = Item.Scratch;
- break;
- }
- case 'd':
- ValueToString (
- Item.Scratch,
- Item.Comma,
- Item.Long ? va_arg(ps->args, INT64) : va_arg(ps->args, INT32)
- );
- Item.Item.pw = Item.Scratch;
- break;
- case 'E':
- Attr = ps->AttrError;
- break;
- case 'e':
- PSETATTR(ps, ps->AttrError);
- break;
- case 'f':
- FloatToString (
- Item.Scratch,
- Item.Comma,
- va_arg(ps->args, double)
- );
- Item.Item.pw = Item.Scratch;
- break;
- case 'g':
- GuidToString (Item.Scratch, va_arg(ps->args, EFI_GUID *));
- Item.Item.pw = Item.Scratch;
- break;
- case 'H':
- Attr = ps->AttrHighlight;
- break;
- case 'h':
- PSETATTR(ps, ps->AttrHighlight);
- break;
- case 'l':
- Item.Long = TRUE;
- break;
- case 'N':
- Attr = ps->AttrNorm;
- break;
- case 'n':
- PSETATTR(ps, ps->AttrNorm);
- break;
- case 'p':
- Item.Width = sizeof(void *) == (8 ? 16 : 8) + 2;
- Item.Pad = '0';
- Item.Scratch[0] = ' ';
- Item.Scratch[1] = ' ';
- ValueToHex (
- Item.Scratch+2,
- Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
- );
- Item.Scratch[0] = '0';
- Item.Scratch[1] = 'x';
- Item.Item.pw = Item.Scratch;
- break;
- case 'r':
- StatusToString (Item.Scratch, va_arg(ps->args, EFI_STATUS));
- Item.Item.pw = Item.Scratch;
- break;
- case 's':
- Item.Item.pw = va_arg(ps->args, CHAR16 *);
- if (!Item.Item.pw) {
- Item.Item.pw = L"(null)";
- }
- break;
- case 't':
- TimeToString (Item.Scratch, va_arg(ps->args, EFI_TIME *));
- Item.Item.pw = Item.Scratch;
- break;
- case 'u':
- ValueToString (
- Item.Scratch,
- Item.Comma,
- Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
- );
- Item.Item.pw = Item.Scratch;
- break;
- case 'X':
- Item.Width = Item.Long ? 16 : 8;
- Item.Pad = '0';
- #if __GNUC__ >= 7
- __attribute__ ((fallthrough));
- #endif
- case 'x':
- ValueToHex (
- Item.Scratch,
- Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
- );
- Item.Item.pw = Item.Scratch;
- break;
- default:
- Item.Scratch[0] = '?';
- Item.Scratch[1] = 0;
- Item.Item.pw = Item.Scratch;
- 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) {
- // Without the cast, the MSVC compiler may insert a reference to __allmull
- *(p1++) = Hex[(UINTN)(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 = (UINTN) (Comma ? ca[(p1 - str) % 3] : 999) + 1;
- while (p1 != str) {
- c -= 1;
- if (!c) {
- *(p2++) = ',';
- c = 3;
- }
- *(p2++) = *(--p1);
- }
- *p2 = 0;
- }
- VOID
- FloatToString (
- IN CHAR16 *Buffer,
- IN BOOLEAN Comma,
- IN double v
- )
- {
- /*
- * Integer part.
- */
- INTN i = (INTN)v;
- ValueToString(Buffer, Comma, i);
- /*
- * Decimal point.
- */
- UINTN x = StrLen(Buffer);
- Buffer[x] = L'.';
- x++;
- /*
- * Keep fractional part.
- */
- float f = (float)(v - i);
- if (f < 0) f = -f;
- /*
- * Leading fractional zeroes.
- */
- f *= 10.0;
- while ( (f != 0)
- && ((INTN)f == 0))
- {
- Buffer[x] = L'0';
- x++;
- f *= 10.0;
- }
- /*
- * Fractional digits.
- */
- while ((float)(INTN)f != f)
- {
- f *= 10;
- }
- ValueToString(Buffer + x, FALSE, (INTN)f);
- return;
- }
- 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
- UnicodeSPrint (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");
- }
- }
- }
|