print.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  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. SPrint (
  326. OUT CHAR16 *Str,
  327. IN UINTN StrSize,
  328. IN CHAR16 *fmt,
  329. ...
  330. )
  331. /*++
  332. Routine Description:
  333. Prints a formatted unicode string to a buffer
  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. Returns:
  340. String length returned in buffer
  341. --*/
  342. {
  343. POOL_PRINT spc;
  344. va_list args;
  345. va_start (args, fmt);
  346. spc.str = Str;
  347. spc.maxlen = StrSize / sizeof(CHAR16) - 1;
  348. spc.len = 0;
  349. _PoolCatPrint (fmt, args, &spc, _SPrint);
  350. va_end (args);
  351. return spc.len;
  352. }
  353. CHAR16 *
  354. PoolPrint (
  355. IN CHAR16 *fmt,
  356. ...
  357. )
  358. /*++
  359. Routine Description:
  360. Prints a formatted unicode string to allocated pool. The caller
  361. must free the resulting buffer.
  362. Arguments:
  363. fmt - The format string
  364. Returns:
  365. Allocated buffer with the formatted string printed in it.
  366. The caller must free the allocated buffer. The buffer
  367. allocation is not packed.
  368. --*/
  369. {
  370. POOL_PRINT spc;
  371. va_list args;
  372. ZeroMem (&spc, sizeof(spc));
  373. va_start (args, fmt);
  374. _PoolCatPrint (fmt, args, &spc, _PoolPrint);
  375. va_end (args);
  376. return spc.str;
  377. }
  378. CHAR16 *
  379. CatPrint (
  380. IN OUT POOL_PRINT *Str,
  381. IN CHAR16 *fmt,
  382. ...
  383. )
  384. /*++
  385. Routine Description:
  386. Concatenates a formatted unicode string to allocated pool.
  387. The caller must free the resulting buffer.
  388. Arguments:
  389. Str - Tracks the allocated pool, size in use, and
  390. amount of pool allocated.
  391. fmt - The format string
  392. Returns:
  393. Allocated buffer with the formatted string printed in it.
  394. The caller must free the allocated buffer. The buffer
  395. allocation is not packed.
  396. --*/
  397. {
  398. va_list args;
  399. va_start (args, fmt);
  400. _PoolCatPrint (fmt, args, Str, _PoolPrint);
  401. va_end (args);
  402. return Str->str;
  403. }
  404. UINTN
  405. Print (
  406. IN CHAR16 *fmt,
  407. ...
  408. )
  409. /*++
  410. Routine Description:
  411. Prints a formatted unicode string to the default console
  412. Arguments:
  413. fmt - Format string
  414. Returns:
  415. Length of string printed to the console
  416. --*/
  417. {
  418. va_list args;
  419. UINTN back;
  420. va_start (args, fmt);
  421. back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
  422. va_end (args);
  423. return back;
  424. }
  425. UINTN
  426. VPrint (
  427. IN CHAR16 *fmt,
  428. va_list args
  429. )
  430. /*++
  431. Routine Description:
  432. Prints a formatted unicode string to the default console using a va_list
  433. Arguments:
  434. fmt - Format string
  435. args - va_list
  436. Returns:
  437. Length of string printed to the console
  438. --*/
  439. {
  440. return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
  441. }
  442. UINTN
  443. PrintAt (
  444. IN UINTN Column,
  445. IN UINTN Row,
  446. IN CHAR16 *fmt,
  447. ...
  448. )
  449. /*++
  450. Routine Description:
  451. Prints a formatted unicode string to the default console, at
  452. the supplied cursor position
  453. Arguments:
  454. Column, Row - The cursor position to print the string at
  455. fmt - Format string
  456. Returns:
  457. Length of string printed to the console
  458. --*/
  459. {
  460. va_list args;
  461. UINTN back;
  462. va_start (args, fmt);
  463. back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
  464. va_end (args);
  465. return back;
  466. }
  467. UINTN
  468. IPrint (
  469. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  470. IN CHAR16 *fmt,
  471. ...
  472. )
  473. /*++
  474. Routine Description:
  475. Prints a formatted unicode string to the specified console
  476. Arguments:
  477. Out - The console to print the string too
  478. fmt - Format string
  479. Returns:
  480. Length of string printed to the console
  481. --*/
  482. {
  483. va_list args;
  484. UINTN back;
  485. va_start (args, fmt);
  486. back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
  487. va_end (args);
  488. return back;
  489. }
  490. UINTN
  491. IPrintAt (
  492. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  493. IN UINTN Column,
  494. IN UINTN Row,
  495. IN CHAR16 *fmt,
  496. ...
  497. )
  498. /*++
  499. Routine Description:
  500. Prints a formatted unicode string to the specified console, at
  501. the supplied cursor position
  502. Arguments:
  503. Out - The console to print the string too
  504. Column, Row - The cursor position to print the string at
  505. fmt - Format string
  506. Returns:
  507. Length of string printed to the console
  508. --*/
  509. {
  510. va_list args;
  511. UINTN back;
  512. va_start (args, fmt);
  513. back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
  514. va_end (args);
  515. return back;
  516. }
  517. UINTN
  518. _IPrint (
  519. IN UINTN Column,
  520. IN UINTN Row,
  521. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  522. IN CHAR16 *fmt,
  523. IN CHAR8 *fmta,
  524. IN va_list args
  525. )
  526. // Display string worker for: Print, PrintAt, IPrint, IPrintAt
  527. {
  528. PRINT_STATE ps;
  529. UINTN back;
  530. ZeroMem (&ps, sizeof(ps));
  531. ps.Context = Out;
  532. ps.Output = (INTN EFIAPI (*)(VOID *, CHAR16 *)) Out->OutputString;
  533. ps.SetAttr = (INTN EFIAPI (*)(VOID *, UINTN)) Out->SetAttribute;
  534. ps.Attr = Out->Mode->Attribute;
  535. back = (ps.Attr >> 4) & 0xF;
  536. ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
  537. ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
  538. ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
  539. if (fmt) {
  540. ps.fmt.pw = fmt;
  541. } else {
  542. ps.fmt.Ascii = TRUE;
  543. ps.fmt.pc = fmta;
  544. }
  545. va_copy(ps.args, args);
  546. if (Column != (UINTN) -1) {
  547. uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row);
  548. }
  549. back = _Print (&ps);
  550. va_end(ps.args);
  551. return back;
  552. }
  553. UINTN
  554. APrint (
  555. IN CHAR8 *fmt,
  556. ...
  557. )
  558. /*++
  559. Routine Description:
  560. For those whom really can't deal with unicode, a print
  561. function that takes an ascii format string
  562. Arguments:
  563. fmt - ascii format string
  564. Returns:
  565. Length of string printed to the console
  566. --*/
  567. {
  568. va_list args;
  569. UINTN back;
  570. va_start (args, fmt);
  571. back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
  572. va_end (args);
  573. return back;
  574. }
  575. STATIC
  576. VOID
  577. PFLUSH (
  578. IN OUT PRINT_STATE *ps
  579. )
  580. {
  581. *ps->Pos = 0;
  582. if (IsLocalPrint(ps->Output))
  583. ps->Output(ps->Context, ps->Buffer);
  584. else
  585. uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
  586. ps->Pos = ps->Buffer;
  587. }
  588. STATIC
  589. VOID
  590. PSETATTR (
  591. IN OUT PRINT_STATE *ps,
  592. IN UINTN Attr
  593. )
  594. {
  595. PFLUSH (ps);
  596. ps->RestoreAttr = ps->Attr;
  597. if (ps->SetAttr) {
  598. uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
  599. }
  600. ps->Attr = Attr;
  601. }
  602. STATIC
  603. VOID
  604. PPUTC (
  605. IN OUT PRINT_STATE *ps,
  606. IN CHAR16 c
  607. )
  608. {
  609. // if this is a newline, add a carraige return
  610. if (c == '\n') {
  611. PPUTC (ps, '\r');
  612. }
  613. *ps->Pos = c;
  614. ps->Pos += 1;
  615. ps->Len += 1;
  616. // if at the end of the buffer, flush it
  617. if (ps->Pos >= ps->End) {
  618. PFLUSH(ps);
  619. }
  620. }
  621. STATIC
  622. CHAR16
  623. PGETC (
  624. IN POINTER *p
  625. )
  626. {
  627. CHAR16 c;
  628. c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
  629. p->Index += 1;
  630. return c;
  631. }
  632. STATIC
  633. VOID
  634. PITEM (
  635. IN OUT PRINT_STATE *ps
  636. )
  637. {
  638. UINTN Len, i;
  639. PRINT_ITEM *Item;
  640. CHAR16 c;
  641. // Get the length of the item
  642. Item = ps->Item;
  643. Item->Item.Index = 0;
  644. while (Item->Item.Index < Item->FieldWidth) {
  645. c = PGETC(&Item->Item);
  646. if (!c) {
  647. Item->Item.Index -= 1;
  648. break;
  649. }
  650. }
  651. Len = Item->Item.Index;
  652. // if there is no item field width, use the items width
  653. if (Item->FieldWidth == (UINTN) -1) {
  654. Item->FieldWidth = Len;
  655. }
  656. // if item is larger then width, update width
  657. if (Len > Item->Width) {
  658. Item->Width = Len;
  659. }
  660. // if pad field before, add pad char
  661. if (Item->PadBefore) {
  662. for (i=Item->Width; i < Item->FieldWidth; i+=1) {
  663. PPUTC (ps, ' ');
  664. }
  665. }
  666. // pad item
  667. for (i=Len; i < Item->Width; i++) {
  668. PPUTC (ps, Item->Pad);
  669. }
  670. // add the item
  671. Item->Item.Index=0;
  672. while (Item->Item.Index < Len) {
  673. PPUTC (ps, PGETC(&Item->Item));
  674. }
  675. // If pad at the end, add pad char
  676. if (!Item->PadBefore) {
  677. for (i=Item->Width; i < Item->FieldWidth; i+=1) {
  678. PPUTC (ps, ' ');
  679. }
  680. }
  681. }
  682. STATIC
  683. UINTN
  684. _Print (
  685. IN PRINT_STATE *ps
  686. )
  687. /*++
  688. Routine Description:
  689. %w.lF - w = width
  690. l = field width
  691. F = format of arg
  692. Args F:
  693. 0 - pad with zeros
  694. - - justify on left (default is on right)
  695. , - add comma's to field
  696. * - width provided on stack
  697. n - Set output attribute to normal (for this field only)
  698. h - Set output attribute to highlight (for this field only)
  699. e - Set output attribute to error (for this field only)
  700. l - Value is 64 bits
  701. a - ascii string
  702. s - unicode string
  703. X - fixed 8 byte value in hex
  704. x - hex value
  705. d - value as decimal
  706. c - Unicode char
  707. t - EFI time structure
  708. g - Pointer to GUID
  709. r - EFI status code (result code)
  710. N - Set output attribute to normal
  711. H - Set output attribute to highlight
  712. E - Set output attribute to error
  713. % - Print a %
  714. Arguments:
  715. SystemTable - The system table
  716. Returns:
  717. Number of charactors written
  718. --*/
  719. {
  720. CHAR16 c;
  721. UINTN Attr;
  722. PRINT_ITEM Item;
  723. CHAR16 Buffer[PRINT_STRING_LEN];
  724. ps->Len = 0;
  725. ps->Buffer = Buffer;
  726. ps->Pos = Buffer;
  727. ps->End = Buffer + PRINT_STRING_LEN - 1;
  728. ps->Item = &Item;
  729. ps->fmt.Index = 0;
  730. while ((c = PGETC(&ps->fmt))) {
  731. if (c != '%') {
  732. PPUTC ( ps, c );
  733. continue;
  734. }
  735. // setup for new item
  736. Item.FieldWidth = (UINTN) -1;
  737. Item.Width = 0;
  738. Item.WidthParse = &Item.Width;
  739. Item.Pad = ' ';
  740. Item.PadBefore = TRUE;
  741. Item.Comma = FALSE;
  742. Item.Long = FALSE;
  743. Item.Item.Ascii = FALSE;
  744. Item.Item.pw = NULL;
  745. ps->RestoreAttr = 0;
  746. Attr = 0;
  747. while ((c = PGETC(&ps->fmt))) {
  748. switch (c) {
  749. case '%':
  750. //
  751. // %% -> %
  752. //
  753. Item.Item.pw = Item.Scratch;
  754. Item.Item.pw[0] = '%';
  755. Item.Item.pw[1] = 0;
  756. break;
  757. case '0':
  758. Item.Pad = '0';
  759. break;
  760. case '-':
  761. Item.PadBefore = FALSE;
  762. break;
  763. case ',':
  764. Item.Comma = TRUE;
  765. break;
  766. case '.':
  767. Item.WidthParse = &Item.FieldWidth;
  768. break;
  769. case '*':
  770. *Item.WidthParse = va_arg(ps->args, UINTN);
  771. break;
  772. case '1':
  773. case '2':
  774. case '3':
  775. case '4':
  776. case '5':
  777. case '6':
  778. case '7':
  779. case '8':
  780. case '9':
  781. *Item.WidthParse = 0;
  782. do {
  783. *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
  784. c = PGETC(&ps->fmt);
  785. } while (c >= '0' && c <= '9') ;
  786. ps->fmt.Index -= 1;
  787. break;
  788. case 'a':
  789. Item.Item.pc = va_arg(ps->args, CHAR8 *);
  790. Item.Item.Ascii = TRUE;
  791. if (!Item.Item.pc) {
  792. Item.Item.pc = (CHAR8 *)"(null)";
  793. }
  794. break;
  795. case 's':
  796. Item.Item.pw = va_arg(ps->args, CHAR16 *);
  797. if (!Item.Item.pw) {
  798. Item.Item.pw = L"(null)";
  799. }
  800. break;
  801. case 'c':
  802. Item.Item.pw = Item.Scratch;
  803. Item.Item.pw[0] = (CHAR16) va_arg(ps->args, UINTN);
  804. Item.Item.pw[1] = 0;
  805. break;
  806. case 'l':
  807. Item.Long = TRUE;
  808. break;
  809. case 'X':
  810. Item.Width = Item.Long ? 16 : 8;
  811. Item.Pad = '0';
  812. case 'x':
  813. Item.Item.pw = Item.Scratch;
  814. ValueToHex (
  815. Item.Item.pw,
  816. Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
  817. );
  818. break;
  819. case 'g':
  820. Item.Item.pw = Item.Scratch;
  821. GuidToString (Item.Item.pw, va_arg(ps->args, EFI_GUID *));
  822. break;
  823. case 'd':
  824. Item.Item.pw = Item.Scratch;
  825. ValueToString (
  826. Item.Item.pw,
  827. Item.Comma,
  828. Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
  829. );
  830. break
  831. ;
  832. case 't':
  833. Item.Item.pw = Item.Scratch;
  834. TimeToString (Item.Item.pw, va_arg(ps->args, EFI_TIME *));
  835. break;
  836. case 'r':
  837. Item.Item.pw = Item.Scratch;
  838. StatusToString (Item.Item.pw, va_arg(ps->args, EFI_STATUS));
  839. break;
  840. case 'n':
  841. PSETATTR(ps, ps->AttrNorm);
  842. break;
  843. case 'h':
  844. PSETATTR(ps, ps->AttrHighlight);
  845. break;
  846. case 'e':
  847. PSETATTR(ps, ps->AttrError);
  848. break;
  849. case 'N':
  850. Attr = ps->AttrNorm;
  851. break;
  852. case 'H':
  853. Attr = ps->AttrHighlight;
  854. break;
  855. case 'E':
  856. Attr = ps->AttrError;
  857. break;
  858. default:
  859. Item.Item.pw = Item.Scratch;
  860. Item.Item.pw[0] = '?';
  861. Item.Item.pw[1] = 0;
  862. break;
  863. }
  864. // if we have an Item
  865. if (Item.Item.pw) {
  866. PITEM (ps);
  867. break;
  868. }
  869. // if we have an Attr set
  870. if (Attr) {
  871. PSETATTR(ps, Attr);
  872. ps->RestoreAttr = 0;
  873. break;
  874. }
  875. }
  876. if (ps->RestoreAttr) {
  877. PSETATTR(ps, ps->RestoreAttr);
  878. }
  879. }
  880. // Flush buffer
  881. PFLUSH (ps);
  882. return ps->Len;
  883. }
  884. STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
  885. '8','9','A','B','C','D','E','F'};
  886. VOID
  887. ValueToHex (
  888. IN CHAR16 *Buffer,
  889. IN UINT64 v
  890. )
  891. {
  892. CHAR8 str[30], *p1;
  893. CHAR16 *p2;
  894. if (!v) {
  895. Buffer[0] = '0';
  896. Buffer[1] = 0;
  897. return ;
  898. }
  899. p1 = str;
  900. p2 = Buffer;
  901. while (v) {
  902. *(p1++) = Hex[v & 0xf];
  903. v = RShiftU64 (v, 4);
  904. }
  905. while (p1 != str) {
  906. *(p2++) = *(--p1);
  907. }
  908. *p2 = 0;
  909. }
  910. VOID
  911. ValueToString (
  912. IN CHAR16 *Buffer,
  913. IN BOOLEAN Comma,
  914. IN INT64 v
  915. )
  916. {
  917. STATIC CHAR8 ca[] = { 3, 1, 2 };
  918. CHAR8 str[40], *p1;
  919. CHAR16 *p2;
  920. UINTN c, r;
  921. if (!v) {
  922. Buffer[0] = '0';
  923. Buffer[1] = 0;
  924. return ;
  925. }
  926. p1 = str;
  927. p2 = Buffer;
  928. if (v < 0) {
  929. *(p2++) = '-';
  930. v = -v;
  931. }
  932. while (v) {
  933. v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
  934. *(p1++) = (CHAR8)r + '0';
  935. }
  936. c = (Comma ? ca[(p1 - str) % 3] : 999) + 1;
  937. while (p1 != str) {
  938. c -= 1;
  939. if (!c) {
  940. *(p2++) = ',';
  941. c = 3;
  942. }
  943. *(p2++) = *(--p1);
  944. }
  945. *p2 = 0;
  946. }
  947. VOID
  948. TimeToString (
  949. OUT CHAR16 *Buffer,
  950. IN EFI_TIME *Time
  951. )
  952. {
  953. UINTN Hour, Year;
  954. CHAR16 AmPm;
  955. AmPm = 'a';
  956. Hour = Time->Hour;
  957. if (Time->Hour == 0) {
  958. Hour = 12;
  959. } else if (Time->Hour >= 12) {
  960. AmPm = 'p';
  961. if (Time->Hour >= 13) {
  962. Hour -= 12;
  963. }
  964. }
  965. Year = Time->Year % 100;
  966. // bugbug: for now just print it any old way
  967. SPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c",
  968. Time->Month,
  969. Time->Day,
  970. Year,
  971. Hour,
  972. Time->Minute,
  973. AmPm
  974. );
  975. }
  976. VOID
  977. DumpHex (
  978. IN UINTN Indent,
  979. IN UINTN Offset,
  980. IN UINTN DataSize,
  981. IN VOID *UserData
  982. )
  983. {
  984. CHAR8 *Data, Val[50], Str[20], c;
  985. UINTN Size, Index;
  986. UINTN ScreenCount;
  987. UINTN TempColumn;
  988. UINTN ScreenSize;
  989. CHAR16 ReturnStr[1];
  990. uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
  991. ScreenCount = 0;
  992. ScreenSize -= 2;
  993. Data = UserData;
  994. while (DataSize) {
  995. Size = 16;
  996. if (Size > DataSize) {
  997. Size = DataSize;
  998. }
  999. for (Index=0; Index < Size; Index += 1) {
  1000. c = Data[Index];
  1001. Val[Index*3+0] = Hex[c>>4];
  1002. Val[Index*3+1] = Hex[c&0xF];
  1003. Val[Index*3+2] = (Index == 7)?'-':' ';
  1004. Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
  1005. }
  1006. Val[Index*3] = 0;
  1007. Str[Index] = 0;
  1008. Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
  1009. Data += Size;
  1010. Offset += Size;
  1011. DataSize -= Size;
  1012. ScreenCount++;
  1013. if (ScreenCount >= ScreenSize && ScreenSize != 0) {
  1014. //
  1015. // If ScreenSize == 0 we have the console redirected so don't
  1016. // block updates
  1017. //
  1018. ScreenCount = 0;
  1019. Print (L"Press Enter to continue :");
  1020. Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
  1021. Print (L"\n");
  1022. }
  1023. }
  1024. }