print.c 26 KB

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