Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1250 lines
24 KiB

  1. /*++
  2. Copyright (c) 1998 Intel Corporation
  3. Module Name:
  4. print.c
  5. Abstract:
  6. Revision History
  7. --*/
  8. #include "lib.h"
  9. #include "efistdarg.h" /* !!! */
  10. /*
  11. * Declare runtime functions
  12. */
  13. #ifdef RUNTIME_CODE
  14. #pragma RUNTIME_CODE(DbgPrint)
  15. /* For debugging.. */
  16. /*
  17. #pragma RUNTIME_CODE(_Print)
  18. #pragma RUNTIME_CODE(PFLUSH)
  19. #pragma RUNTIME_CODE(PSETATTR)
  20. #pragma RUNTIME_CODE(PPUTC)
  21. #pragma RUNTIME_CODE(PGETC)
  22. #pragma RUNTIME_CODE(PITEM)
  23. #pragma RUNTIME_CODE(ValueToHex)
  24. #pragma RUNTIME_CODE(ValueToString)
  25. #pragma RUNTIME_CODE(TimeToString)
  26. */
  27. #endif
  28. /*
  29. *
  30. */
  31. #define PRINT_STRING_LEN 200
  32. #define PRINT_ITEM_BUFFER_LEN 100
  33. typedef struct {
  34. BOOLEAN Ascii;
  35. UINTN Index;
  36. union {
  37. CHAR16 *pw;
  38. CHAR8 *pc;
  39. } ;
  40. } POINTER;
  41. typedef struct _pitem {
  42. POINTER Item;
  43. CHAR16 Scratch[PRINT_ITEM_BUFFER_LEN];
  44. UINTN Width;
  45. UINTN FieldWidth;
  46. UINTN *WidthParse;
  47. CHAR16 Pad;
  48. BOOLEAN PadBefore;
  49. BOOLEAN Comma;
  50. BOOLEAN Long;
  51. } PRINT_ITEM;
  52. typedef struct _pstate {
  53. /* Input */
  54. POINTER fmt;
  55. va_list args;
  56. /* Output */
  57. CHAR16 *Buffer;
  58. CHAR16 *End;
  59. CHAR16 *Pos;
  60. UINTN Len;
  61. UINTN Attr;
  62. UINTN RestoreAttr;
  63. UINTN AttrNorm;
  64. UINTN AttrHighlight;
  65. UINTN AttrError;
  66. INTN (*Output)(VOID *context, CHAR16 *str);
  67. INTN (*SetAttr)(VOID *context, UINTN attr);
  68. VOID *Context;
  69. /* Current item being formatted */
  70. struct _pitem *Item;
  71. } PRINT_STATE;
  72. /*
  73. * Internal fucntions
  74. */
  75. STATIC
  76. UINTN
  77. _Print (
  78. IN PRINT_STATE *ps
  79. );
  80. STATIC
  81. UINTN
  82. _IPrint (
  83. IN UINTN Column,
  84. IN UINTN Row,
  85. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  86. IN CHAR16 *fmt,
  87. IN CHAR8 *fmta,
  88. IN va_list args
  89. );
  90. STATIC
  91. INTN
  92. _DbgOut (
  93. IN VOID *Context,
  94. IN CHAR16 *Buffer
  95. );
  96. STATIC
  97. VOID
  98. PFLUSH (
  99. IN OUT PRINT_STATE *ps
  100. );
  101. STATIC
  102. VOID
  103. PPUTC (
  104. IN OUT PRINT_STATE *ps,
  105. IN CHAR16 c
  106. );
  107. STATIC
  108. VOID
  109. PITEM (
  110. IN OUT PRINT_STATE *ps
  111. );
  112. STATIC
  113. CHAR16
  114. PGETC (
  115. IN POINTER *p
  116. );
  117. STATIC
  118. VOID
  119. PSETATTR (
  120. IN OUT PRINT_STATE *ps,
  121. IN UINTN Attr
  122. );
  123. /*
  124. *
  125. */
  126. INTN
  127. DbgPrint (
  128. IN INTN mask,
  129. IN CHAR8 *fmt,
  130. ...
  131. )
  132. /*++
  133. Routine Description:
  134. Prints a formatted unicode string to the default StandardError console
  135. Arguments:
  136. mask - Bit mask of debug string. If a bit is set in the
  137. mask that is also set in EFIDebug the string is
  138. printed; otherwise, the string is not printed
  139. fmt - Format string
  140. Returns:
  141. Length of string printed to the StandardError console
  142. --*/
  143. {
  144. SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
  145. PRINT_STATE ps;
  146. va_list args;
  147. UINTN back;
  148. UINTN attr;
  149. UINTN SavedAttribute;
  150. if (!(EFIDebug & mask)) {
  151. return 0;
  152. }
  153. va_start (args, fmt);
  154. ZeroMem (&ps, sizeof(ps));
  155. ps.Output = _DbgOut;
  156. ps.fmt.Ascii = TRUE;
  157. ps.fmt.pc = fmt;
  158. ps.args = args;
  159. ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED);
  160. DbgOut = LibRuntimeDebugOut;
  161. if (!DbgOut) {
  162. DbgOut = ST->StdErr;
  163. }
  164. if (DbgOut) {
  165. ps.Attr = DbgOut->Mode->Attribute;
  166. ps.Context = DbgOut;
  167. ps.SetAttr = (INTN (*)(VOID *, UINTN)) DbgOut->SetAttribute;
  168. }
  169. SavedAttribute = ps.Attr;
  170. back = (ps.Attr >> 4) & 0xf;
  171. ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
  172. ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
  173. ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
  174. attr = ps.AttrNorm;
  175. if (mask & D_WARN) {
  176. attr = ps.AttrHighlight;
  177. }
  178. if (mask & D_ERROR) {
  179. attr = ps.AttrError;
  180. }
  181. if (ps.SetAttr) {
  182. ps.Attr = attr;
  183. ps.SetAttr (ps.Context, attr);
  184. }
  185. _Print (&ps);
  186. /*
  187. * Restore original attributes
  188. */
  189. if (ps.SetAttr) {
  190. ps.SetAttr (ps.Context, SavedAttribute);
  191. }
  192. return 0;
  193. }
  194. STATIC
  195. INTN
  196. _DbgOut (
  197. IN VOID *Context,
  198. IN CHAR16 *Buffer
  199. )
  200. /* Append string worker for DbgPrint */
  201. {
  202. SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut;
  203. DbgOut = Context;
  204. /* if (!DbgOut && ST && ST->ConOut) {
  205. * DbgOut = ST->ConOut;
  206. * } */
  207. if (DbgOut) {
  208. DbgOut->OutputString (DbgOut, Buffer);
  209. }
  210. return 0;
  211. }
  212. INTN
  213. _SPrint (
  214. IN VOID *Context,
  215. IN CHAR16 *Buffer
  216. )
  217. /* Append string worker for SPrint, PoolPrint and CatPrint */
  218. {
  219. UINTN len;
  220. POOL_PRINT *spc;
  221. spc = Context;
  222. len = StrLen(Buffer);
  223. /*
  224. * Is the string is over the max truncate it
  225. */
  226. if (spc->len + len > spc->maxlen) {
  227. len = spc->maxlen - spc->len;
  228. }
  229. /*
  230. * Append the new text
  231. */
  232. CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16));
  233. spc->len += len;
  234. /*
  235. * Null terminate it
  236. */
  237. if (spc->len < spc->maxlen) {
  238. spc->str[spc->len] = 0;
  239. } else if (spc->maxlen) {
  240. spc->str[spc->maxlen-1] = 0;
  241. }
  242. return 0;
  243. }
  244. INTN
  245. _PoolPrint (
  246. IN VOID *Context,
  247. IN CHAR16 *Buffer
  248. )
  249. /* Append string worker for PoolPrint and CatPrint */
  250. {
  251. UINTN newlen;
  252. POOL_PRINT *spc;
  253. spc = Context;
  254. newlen = spc->len + StrLen(Buffer) + 1;
  255. /*
  256. * Is the string is over the max, grow the buffer
  257. */
  258. if (newlen > spc->maxlen) {
  259. /*
  260. * Grow the pool buffer
  261. */
  262. newlen += PRINT_STRING_LEN;
  263. spc->maxlen = newlen;
  264. spc->str = ReallocatePool (
  265. spc->str,
  266. spc->len * sizeof(CHAR16),
  267. spc->maxlen * sizeof(CHAR16)
  268. );
  269. if (!spc->str) {
  270. spc->len = 0;
  271. spc->maxlen = 0;
  272. }
  273. }
  274. /*
  275. * Append the new text
  276. */
  277. return _SPrint (Context, Buffer);
  278. }
  279. VOID
  280. _PoolCatPrint (
  281. IN CHAR16 *fmt,
  282. IN va_list args,
  283. IN OUT POOL_PRINT *spc,
  284. IN INTN (*Output)(VOID *context, CHAR16 *str)
  285. )
  286. /* Dispath function for SPrint, PoolPrint, and CatPrint */
  287. {
  288. PRINT_STATE ps;
  289. ZeroMem (&ps, sizeof(ps));
  290. ps.Output = Output;
  291. ps.Context = spc;
  292. ps.fmt.pw = fmt;
  293. ps.args = args;
  294. _Print (&ps);
  295. }
  296. UINTN
  297. SPrint (
  298. OUT CHAR16 *Str,
  299. IN UINTN StrSize,
  300. IN CHAR16 *fmt,
  301. ...
  302. )
  303. /*++
  304. Routine Description:
  305. Prints a formatted unicode string to a buffer
  306. Arguments:
  307. Str - Output buffer to print the formatted string into
  308. StrSize - Size of Str. String is truncated to this size.
  309. A size of 0 means there is no limit
  310. fmt - The format string
  311. Returns:
  312. String length returned in buffer
  313. --*/
  314. {
  315. POOL_PRINT spc;
  316. va_list args;
  317. va_start (args, fmt);
  318. spc.str = Str;
  319. spc.maxlen = StrSize / sizeof(CHAR16) - 1;
  320. spc.len = 0;
  321. _PoolCatPrint (fmt, args, &spc, _SPrint);
  322. return spc.len;
  323. }
  324. CHAR16 *
  325. PoolPrint (
  326. IN CHAR16 *fmt,
  327. ...
  328. )
  329. /*++
  330. Routine Description:
  331. Prints a formatted unicode string to allocated pool. The caller
  332. must free the resulting buffer.
  333. Arguments:
  334. fmt - The format string
  335. Returns:
  336. Allocated buffer with the formatted string printed in it.
  337. The caller must free the allocated buffer. The buffer
  338. allocation is not packed.
  339. --*/
  340. {
  341. POOL_PRINT spc;
  342. va_list args;
  343. ZeroMem (&spc, sizeof(spc));
  344. va_start (args, fmt);
  345. _PoolCatPrint (fmt, args, &spc, _PoolPrint);
  346. return spc.str;
  347. }
  348. CHAR16 *
  349. CatPrint (
  350. IN OUT POOL_PRINT *Str,
  351. IN CHAR16 *fmt,
  352. ...
  353. )
  354. /*++
  355. Routine Description:
  356. Concatenates a formatted unicode string to allocated pool.
  357. The caller must free the resulting buffer.
  358. Arguments:
  359. Str - Tracks the allocated pool, size in use, and
  360. amount of pool allocated.
  361. fmt - The format string
  362. Returns:
  363. Allocated buffer with the formatted string printed in it.
  364. The caller must free the allocated buffer. The buffer
  365. allocation is not packed.
  366. --*/
  367. {
  368. va_list args;
  369. va_start (args, fmt);
  370. _PoolCatPrint (fmt, args, Str, _PoolPrint);
  371. return Str->str;
  372. }
  373. UINTN
  374. Print (
  375. IN CHAR16 *fmt,
  376. ...
  377. )
  378. /*++
  379. Routine Description:
  380. Prints a formatted unicode string to the default console
  381. Arguments:
  382. fmt - Format string
  383. Returns:
  384. Length of string printed to the console
  385. --*/
  386. {
  387. va_list args;
  388. va_start (args, fmt);
  389. return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
  390. }
  391. UINTN
  392. PrintAt (
  393. IN UINTN Column,
  394. IN UINTN Row,
  395. IN CHAR16 *fmt,
  396. ...
  397. )
  398. /*++
  399. Routine Description:
  400. Prints a formatted unicode string to the default console, at
  401. the supplied cursor position
  402. Arguments:
  403. Column, Row - The cursor position to print the string at
  404. fmt - Format string
  405. Returns:
  406. Length of string printed to the console
  407. --*/
  408. {
  409. va_list args;
  410. va_start (args, fmt);
  411. return _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
  412. }
  413. UINTN
  414. IPrint (
  415. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  416. IN CHAR16 *fmt,
  417. ...
  418. )
  419. /*++
  420. Routine Description:
  421. Prints a formatted unicode string to the specified console
  422. Arguments:
  423. Out - The console to print the string too
  424. fmt - Format string
  425. Returns:
  426. Length of string printed to the console
  427. --*/
  428. {
  429. va_list args;
  430. va_start (args, fmt);
  431. return _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
  432. }
  433. UINTN
  434. IPrintAt (
  435. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  436. IN UINTN Column,
  437. IN UINTN Row,
  438. IN CHAR16 *fmt,
  439. ...
  440. )
  441. /*++
  442. Routine Description:
  443. Prints a formatted unicode string to the specified console, at
  444. the supplied cursor position
  445. Arguments:
  446. Out - The console to print the string too
  447. Column, Row - The cursor position to print the string at
  448. fmt - Format string
  449. Returns:
  450. Length of string printed to the console
  451. --*/
  452. {
  453. va_list args;
  454. va_start (args, fmt);
  455. return _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
  456. }
  457. UINTN
  458. _IPrint (
  459. IN UINTN Column,
  460. IN UINTN Row,
  461. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  462. IN CHAR16 *fmt,
  463. IN CHAR8 *fmta,
  464. IN va_list args
  465. )
  466. /* Display string worker for: Print, PrintAt, IPrint, IPrintAt */
  467. {
  468. PRINT_STATE ps;
  469. UINTN back;
  470. ZeroMem (&ps, sizeof(ps));
  471. ps.Context = Out;
  472. ps.Output = (INTN (*)(VOID *, CHAR16 *)) Out->OutputString;
  473. ps.SetAttr = (INTN (*)(VOID *, UINTN)) Out->SetAttribute;
  474. ps.Attr = Out->Mode->Attribute;
  475. back = (ps.Attr >> 4) & 0xF;
  476. ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
  477. ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
  478. ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
  479. if (fmt) {
  480. ps.fmt.pw = fmt;
  481. } else {
  482. ps.fmt.Ascii = TRUE;
  483. ps.fmt.pc = fmta;
  484. }
  485. ps.args = args;
  486. if (Column != (UINTN) -1) {
  487. Out->SetCursorPosition(Out, Column, Row);
  488. }
  489. return _Print (&ps);
  490. }
  491. UINTN
  492. APrint (
  493. IN CHAR8 *fmt,
  494. ...
  495. )
  496. /*++
  497. Routine Description:
  498. For those whom really can't deal with unicode, a print
  499. function that takes an ascii format string
  500. Arguments:
  501. fmt - ascii format string
  502. Returns:
  503. Length of string printed to the console
  504. --*/
  505. {
  506. va_list args;
  507. va_start (args, fmt);
  508. return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
  509. }
  510. STATIC
  511. VOID
  512. PFLUSH (
  513. IN OUT PRINT_STATE *ps
  514. )
  515. {
  516. *ps->Pos = 0;
  517. ps->Output(ps->Context, ps->Buffer);
  518. ps->Pos = ps->Buffer;
  519. }
  520. STATIC
  521. VOID
  522. PSETATTR (
  523. IN OUT PRINT_STATE *ps,
  524. IN UINTN Attr
  525. )
  526. {
  527. PFLUSH (ps);
  528. ps->RestoreAttr = ps->Attr;
  529. if (ps->SetAttr) {
  530. ps->SetAttr (ps->Context, Attr);
  531. }
  532. ps->Attr = Attr;
  533. }
  534. STATIC
  535. VOID
  536. PPUTC (
  537. IN OUT PRINT_STATE *ps,
  538. IN CHAR16 c
  539. )
  540. {
  541. /* if this is a newline, add a carraige return */
  542. if (c == '\n') {
  543. PPUTC (ps, '\r');
  544. }
  545. *ps->Pos = c;
  546. ps->Pos += 1;
  547. ps->Len += 1;
  548. /* if at the end of the buffer, flush it */
  549. if (ps->Pos >= ps->End) {
  550. PFLUSH(ps);
  551. }
  552. }
  553. STATIC
  554. CHAR16
  555. PGETC (
  556. IN POINTER *p
  557. )
  558. {
  559. CHAR16 c;
  560. c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
  561. p->Index += 1;
  562. return c;
  563. }
  564. STATIC
  565. VOID
  566. PITEM (
  567. IN OUT PRINT_STATE *ps
  568. )
  569. {
  570. UINTN Len, i;
  571. PRINT_ITEM *Item;
  572. CHAR16 c;
  573. /* Get the length of the item */
  574. Item = ps->Item;
  575. Item->Item.Index = 0;
  576. while (Item->Item.Index < Item->FieldWidth) {
  577. c = PGETC(&Item->Item);
  578. if (!c) {
  579. Item->Item.Index -= 1;
  580. break;
  581. }
  582. }
  583. Len = Item->Item.Index;
  584. /* if there is no item field width, use the items width */
  585. if (Item->FieldWidth == (UINTN) -1) {
  586. Item->FieldWidth = Len;
  587. }
  588. /* if item is larger then width, update width */
  589. if (Len > Item->Width) {
  590. Item->Width = Len;
  591. }
  592. /* if pad field before, add pad char */
  593. if (Item->PadBefore) {
  594. for (i=Item->Width; i < Item->FieldWidth; i+=1) {
  595. PPUTC (ps, ' ');
  596. }
  597. }
  598. /* pad item */
  599. for (i=Len; i < Item->Width; i++) {
  600. PPUTC (ps, Item->Pad);
  601. }
  602. /* add the item */
  603. Item->Item.Index=0;
  604. while (Item->Item.Index < Len) {
  605. PPUTC (ps, PGETC(&Item->Item));
  606. }
  607. /* If pad at the end, add pad char */
  608. if (!Item->PadBefore) {
  609. for (i=Item->Width; i < Item->FieldWidth; i+=1) {
  610. PPUTC (ps, ' ');
  611. }
  612. }
  613. }
  614. STATIC
  615. UINTN
  616. _Print (
  617. IN PRINT_STATE *ps
  618. )
  619. /*++
  620. Routine Description:
  621. %w.lF - w = width
  622. l = field width
  623. F = format of arg
  624. Args F:
  625. 0 - pad with zeros
  626. - - justify on left (default is on right)
  627. , - add comma's to field
  628. * - width provided on stack
  629. n - Set output attribute to normal (for this field only)
  630. h - Set output attribute to highlight (for this field only)
  631. e - Set output attribute to error (for this field only)
  632. l - Value is 64 bits
  633. a - ascii string
  634. s - unicode string
  635. X - fixed 8 byte value in hex
  636. x - hex value
  637. d - value as decimal
  638. c - Unicode char
  639. t - EFI time structure
  640. g - Pointer to GUID
  641. r - EFI status code (result code)
  642. N - Set output attribute to normal
  643. H - Set output attribute to highlight
  644. E - Set output attribute to error
  645. % - Print a %
  646. Arguments:
  647. SystemTable - The system table
  648. Returns:
  649. Number of charactors written
  650. --*/
  651. {
  652. CHAR16 c;
  653. UINTN Attr;
  654. PRINT_ITEM Item;
  655. CHAR16 Buffer[PRINT_STRING_LEN];
  656. ps->Len = 0;
  657. ps->Buffer = Buffer;
  658. ps->Pos = Buffer;
  659. ps->End = Buffer + PRINT_STRING_LEN - 1;
  660. ps->Item = &Item;
  661. ps->fmt.Index = 0;
  662. while (c = PGETC(&ps->fmt)) {
  663. if (c != '%') {
  664. PPUTC ( ps, c );
  665. continue;
  666. }
  667. /* setup for new item */
  668. Item.FieldWidth = (UINTN) -1;
  669. Item.Width = 0;
  670. Item.WidthParse = &Item.Width;
  671. Item.Pad = ' ';
  672. Item.PadBefore = TRUE;
  673. Item.Comma = FALSE;
  674. Item.Long = FALSE;
  675. Item.Item.Ascii = FALSE;
  676. Item.Item.pw = NULL;
  677. ps->RestoreAttr = 0;
  678. Attr = 0;
  679. while (c = PGETC(&ps->fmt)) {
  680. switch (c) {
  681. case '%':
  682. /*
  683. * %% -> %
  684. */
  685. Item.Item.pw = Item.Scratch;
  686. Item.Item.pw[0] = '%';
  687. Item.Item.pw[1] = 0;
  688. break;
  689. case '0':
  690. Item.Pad = '0';
  691. break;
  692. case '-':
  693. Item.PadBefore = FALSE;
  694. break;
  695. case ',':
  696. Item.Comma = TRUE;
  697. break;
  698. case '.':
  699. Item.WidthParse = &Item.FieldWidth;
  700. break;
  701. case '*':
  702. *Item.WidthParse = va_arg(ps->args, UINTN);
  703. break;
  704. case '1':
  705. case '2':
  706. case '3':
  707. case '4':
  708. case '5':
  709. case '6':
  710. case '7':
  711. case '8':
  712. case '9':
  713. *Item.WidthParse = 0;
  714. do {
  715. *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
  716. c = PGETC(&ps->fmt);
  717. } while (c >= '0' && c <= '9') ;
  718. ps->fmt.Index -= 1;
  719. break;
  720. case 'a':
  721. Item.Item.pc = va_arg(ps->args, CHAR8 *);
  722. Item.Item.Ascii = TRUE;
  723. if (!Item.Item.pc) {
  724. Item.Item.pc = "(null)";
  725. }
  726. break;
  727. case 's':
  728. Item.Item.pw = va_arg(ps->args, CHAR16 *);
  729. if (!Item.Item.pw) {
  730. Item.Item.pw = L"(null)";
  731. }
  732. break;
  733. case 'c':
  734. Item.Item.pw = Item.Scratch;
  735. Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
  736. Item.Item.pw[1] = 0;
  737. break;
  738. case 'l':
  739. Item.Long = TRUE;
  740. break;
  741. case 'X':
  742. Item.Width = Item.Long ? 16 : 8;
  743. Item.Pad = '0';
  744. case 'x':
  745. Item.Item.pw = Item.Scratch;
  746. ValueToHex (
  747. Item.Item.pw,
  748. Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINTN)
  749. );
  750. break;
  751. case 'g':
  752. Item.Item.pw = Item.Scratch;
  753. GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
  754. break;
  755. case 'd':
  756. Item.Item.pw = Item.Scratch;
  757. ValueToString (
  758. Item.Item.pw,
  759. Item.Comma,
  760. Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINTN)
  761. );
  762. break
  763. ;
  764. case 't':
  765. Item.Item.pw = Item.Scratch;
  766. TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
  767. break;
  768. case 'r':
  769. Item.Item.pw = Item.Scratch;
  770. StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
  771. break;
  772. case 'n':
  773. PSETATTR(ps, ps->AttrNorm);
  774. break;
  775. case 'h':
  776. PSETATTR(ps, ps->AttrHighlight);
  777. break;
  778. case 'e':
  779. PSETATTR(ps, ps->AttrError);
  780. break;
  781. case 'N':
  782. Attr = ps->AttrNorm;
  783. break;
  784. case 'H':
  785. Attr = ps->AttrHighlight;
  786. break;
  787. case 'E':
  788. Attr = ps->AttrError;
  789. break;
  790. default:
  791. Item.Item.pw = Item.Scratch;
  792. Item.Item.pw[0] = '?';
  793. Item.Item.pw[1] = 0;
  794. break;
  795. }
  796. /* if we have an Item */
  797. if (Item.Item.pw) {
  798. PITEM (ps);
  799. break;
  800. }
  801. /* if we have an Attr set */
  802. if (Attr) {
  803. PSETATTR(ps, Attr);
  804. ps->RestoreAttr = 0;
  805. break;
  806. }
  807. }
  808. if (ps->RestoreAttr) {
  809. PSETATTR(ps, ps->RestoreAttr);
  810. }
  811. }
  812. /* Flush buffer */
  813. PFLUSH (ps);
  814. return ps->Len;
  815. }
  816. STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
  817. '8','9','A','B','C','D','E','F'};
  818. VOID
  819. ValueToHex (
  820. IN CHAR16 *Buffer,
  821. IN UINT64 v
  822. )
  823. {
  824. CHAR8 str[30], *p1;
  825. CHAR16 *p2;
  826. if (!v) {
  827. Buffer[0] = '0';
  828. Buffer[1] = 0;
  829. return ;
  830. }
  831. p1 = str;
  832. p2 = Buffer;
  833. while (v) {
  834. *(p1++) = Hex[v & 0xf];
  835. v = RShiftU64 (v, 4);
  836. }
  837. while (p1 != str) {
  838. *(p2++) = *(--p1);
  839. }
  840. *p2 = 0;
  841. }
  842. VOID
  843. ValueToString (
  844. IN CHAR16 *Buffer,
  845. IN BOOLEAN Comma,
  846. IN INT64 v
  847. )
  848. {
  849. STATIC CHAR8 ca[] = { 3, 1, 2 };
  850. CHAR8 str[40], *p1;
  851. CHAR16 *p2;
  852. UINTN c, r;
  853. if (!v) {
  854. Buffer[0] = '0';
  855. Buffer[1] = 0;
  856. return ;
  857. }
  858. p1 = str;
  859. p2 = Buffer;
  860. if (v < 0) {
  861. *(p2++) = '-';
  862. v = -v;
  863. }
  864. while (v) {
  865. v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
  866. *(p1++) = (CHAR8)r + '0';
  867. }
  868. c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
  869. while (p1 != str) {
  870. c -= 1;
  871. if (!c) {
  872. *(p2++) = ',';
  873. c = 3;
  874. }
  875. *(p2++) = *(--p1);
  876. }
  877. *p2 = 0;
  878. }
  879. VOID
  880. TimeToString (
  881. OUT CHAR16 *Buffer,
  882. IN EFI_TIME *Time
  883. )
  884. {
  885. UINTN Hour, Year;
  886. CHAR16 AmPm;
  887. AmPm = 'a';
  888. Hour = Time->Hour;
  889. if (Time->Hour == 0) {
  890. Hour = 12;
  891. } else if (Time->Hour >= 12) {
  892. AmPm = 'p';
  893. if (Time->Hour >= 13) {
  894. Hour -= 12;
  895. }
  896. }
  897. Year = Time->Year % 100;
  898. /* bugbug: for now just print it any old way */
  899. SPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c",
  900. Time->Month,
  901. Time->Day,
  902. Year,
  903. Hour,
  904. Time->Minute,
  905. AmPm
  906. );
  907. }
  908. VOID
  909. DumpHex (
  910. IN UINTN Indent,
  911. IN UINTN Offset,
  912. IN UINTN DataSize,
  913. IN VOID *UserData
  914. )
  915. {
  916. CHAR8 *Data, Val[50], Str[20], c;
  917. UINTN Size, Index;
  918. UINTN ScreenCount;
  919. UINTN TempColumn;
  920. UINTN ScreenSize;
  921. CHAR16 ReturnStr[1];
  922. ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
  923. ScreenCount = 0;
  924. ScreenSize -= 2;
  925. Data = UserData;
  926. while (DataSize) {
  927. Size = 16;
  928. if (Size > DataSize) {
  929. Size = DataSize;
  930. }
  931. for (Index=0; Index < Size; Index += 1) {
  932. c = Data[Index];
  933. Val[Index*3+0] = Hex[c>>4];
  934. Val[Index*3+1] = Hex[c&0xF];
  935. Val[Index*3+2] = (Index == 7)?'-':' ';
  936. Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
  937. }
  938. Val[Index*3] = 0;
  939. Str[Index] = 0;
  940. Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
  941. Data += Size;
  942. Offset += Size;
  943. DataSize -= Size;
  944. ScreenCount++;
  945. if (ScreenCount >= ScreenSize && ScreenSize != 0) {
  946. /*
  947. * If ScreenSize == 0 we have the console redirected so don't
  948. * block updates
  949. */
  950. ScreenCount = 0;
  951. Print (L"Press Return to contiue :");
  952. Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
  953. Print (L"\n");
  954. }
  955. }
  956. }