Leaked source code of windows server 2003
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.

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