print.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538
  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. CONST CHAR16 *pw;
  40. CONST 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 CONST CHAR16 *fmt,
  91. IN CONST 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 CONST 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. uefi_call_wrapper(ps.SetAttr, 2, 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. uefi_call_wrapper(ps.SetAttr, 2, 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 UnicodeSPrint, 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] = 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 CONST CHAR16 *fmt,
  309. IN va_list args,
  310. IN OUT POOL_PRINT *spc,
  311. IN INTN (EFIAPI *Output)(VOID *context, CHAR16 *str)
  312. )
  313. // Dispatch function for UnicodeSPrint, 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. UnicodeVSPrint (
  326. OUT CHAR16 *Str,
  327. IN UINTN StrSize,
  328. IN CONST 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. UnicodeSPrint (
  353. OUT CHAR16 *Str,
  354. IN UINTN StrSize,
  355. IN CONST 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 = UnicodeVSPrint(Str, StrSize, fmt, args);
  374. va_end (args);
  375. return len;
  376. }
  377. CHAR16 *
  378. VPoolPrint (
  379. IN CONST CHAR16 *fmt,
  380. va_list args
  381. )
  382. /*++
  383. Routine Description:
  384. Prints a formatted unicode string to allocated pool using va_list argument.
  385. The caller must free the resulting buffer.
  386. Arguments:
  387. fmt - The format string
  388. args - The arguments in va_list form
  389. Returns:
  390. Allocated buffer with the formatted string printed in it.
  391. The caller must free the allocated buffer. The buffer
  392. allocation is not packed.
  393. --*/
  394. {
  395. POOL_PRINT spc;
  396. ZeroMem (&spc, sizeof(spc));
  397. _PoolCatPrint (fmt, args, &spc, _PoolPrint);
  398. return spc.str;
  399. }
  400. CHAR16 *
  401. PoolPrint (
  402. IN CONST CHAR16 *fmt,
  403. ...
  404. )
  405. /*++
  406. Routine Description:
  407. Prints a formatted unicode string to allocated pool. The caller
  408. must free the resulting buffer.
  409. Arguments:
  410. fmt - The format string
  411. Returns:
  412. Allocated buffer with the formatted string printed in it.
  413. The caller must free the allocated buffer. The buffer
  414. allocation is not packed.
  415. --*/
  416. {
  417. va_list args;
  418. CHAR16 *pool;
  419. va_start (args, fmt);
  420. pool = VPoolPrint(fmt, args);
  421. va_end (args);
  422. return pool;
  423. }
  424. CHAR16 *
  425. CatPrint (
  426. IN OUT POOL_PRINT *Str,
  427. IN CONST CHAR16 *fmt,
  428. ...
  429. )
  430. /*++
  431. Routine Description:
  432. Concatenates a formatted unicode string to allocated pool.
  433. The caller must free the resulting buffer.
  434. Arguments:
  435. Str - Tracks the allocated pool, size in use, and
  436. amount of pool allocated.
  437. fmt - The format string
  438. Returns:
  439. Allocated buffer with the formatted string printed in it.
  440. The caller must free the allocated buffer. The buffer
  441. allocation is not packed.
  442. --*/
  443. {
  444. va_list args;
  445. va_start (args, fmt);
  446. _PoolCatPrint (fmt, args, Str, _PoolPrint);
  447. va_end (args);
  448. return Str->str;
  449. }
  450. UINTN
  451. Print (
  452. IN CONST CHAR16 *fmt,
  453. ...
  454. )
  455. /*++
  456. Routine Description:
  457. Prints a formatted unicode string to the default console
  458. Arguments:
  459. fmt - Format string
  460. Returns:
  461. Length of string printed to the console
  462. --*/
  463. {
  464. va_list args;
  465. UINTN back;
  466. va_start (args, fmt);
  467. back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
  468. va_end (args);
  469. return back;
  470. }
  471. UINTN
  472. VPrint (
  473. IN CONST CHAR16 *fmt,
  474. va_list args
  475. )
  476. /*++
  477. Routine Description:
  478. Prints a formatted unicode string to the default console using a va_list
  479. Arguments:
  480. fmt - Format string
  481. args - va_list
  482. Returns:
  483. Length of string printed to the console
  484. --*/
  485. {
  486. return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args);
  487. }
  488. UINTN
  489. PrintAt (
  490. IN UINTN Column,
  491. IN UINTN Row,
  492. IN CONST CHAR16 *fmt,
  493. ...
  494. )
  495. /*++
  496. Routine Description:
  497. Prints a formatted unicode string to the default console, at
  498. the supplied cursor position
  499. Arguments:
  500. Column, Row - The cursor position to print the string at
  501. fmt - Format string
  502. Returns:
  503. Length of string printed to the console
  504. --*/
  505. {
  506. va_list args;
  507. UINTN back;
  508. va_start (args, fmt);
  509. back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args);
  510. va_end (args);
  511. return back;
  512. }
  513. UINTN
  514. IPrint (
  515. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  516. IN CONST CHAR16 *fmt,
  517. ...
  518. )
  519. /*++
  520. Routine Description:
  521. Prints a formatted unicode string to the specified console
  522. Arguments:
  523. Out - The console to print the string too
  524. fmt - Format string
  525. Returns:
  526. Length of string printed to the console
  527. --*/
  528. {
  529. va_list args;
  530. UINTN back;
  531. va_start (args, fmt);
  532. back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args);
  533. va_end (args);
  534. return back;
  535. }
  536. UINTN
  537. IPrintAt (
  538. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  539. IN UINTN Column,
  540. IN UINTN Row,
  541. IN CONST CHAR16 *fmt,
  542. ...
  543. )
  544. /*++
  545. Routine Description:
  546. Prints a formatted unicode string to the specified console, at
  547. the supplied cursor position
  548. Arguments:
  549. Out - The console to print the string to
  550. Column, Row - The cursor position to print the string at
  551. fmt - Format string
  552. Returns:
  553. Length of string printed to the console
  554. --*/
  555. {
  556. va_list args;
  557. UINTN back;
  558. va_start (args, fmt);
  559. back = _IPrint (Column, Row, Out, fmt, NULL, args);
  560. va_end (args);
  561. return back;
  562. }
  563. UINTN
  564. _IPrint (
  565. IN UINTN Column,
  566. IN UINTN Row,
  567. IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out,
  568. IN CONST CHAR16 *fmt,
  569. IN CONST CHAR8 *fmta,
  570. IN va_list args
  571. )
  572. // Display string worker for: Print, PrintAt, IPrint, IPrintAt
  573. {
  574. PRINT_STATE ps;
  575. UINTN back;
  576. ZeroMem (&ps, sizeof(ps));
  577. ps.Context = Out;
  578. ps.Output = (INTN (EFIAPI *)(VOID *, CHAR16 *)) Out->OutputString;
  579. ps.SetAttr = (INTN (EFIAPI *)(VOID *, UINTN)) Out->SetAttribute;
  580. ps.Attr = Out->Mode->Attribute;
  581. back = (ps.Attr >> 4) & 0xF;
  582. ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back);
  583. ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back);
  584. ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back);
  585. if (fmt) {
  586. ps.fmt.pw = fmt;
  587. } else {
  588. ps.fmt.Ascii = TRUE;
  589. ps.fmt.pc = fmta;
  590. }
  591. va_copy(ps.args, args);
  592. if (Column != (UINTN) -1) {
  593. uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row);
  594. }
  595. back = _Print (&ps);
  596. va_end(ps.args);
  597. return back;
  598. }
  599. UINTN
  600. AsciiPrint (
  601. IN CONST CHAR8 *fmt,
  602. ...
  603. )
  604. /*++
  605. Routine Description:
  606. For those whom really can't deal with unicode, a print
  607. function that takes an ascii format string
  608. Arguments:
  609. fmt - ascii format string
  610. Returns:
  611. Length of string printed to the console
  612. --*/
  613. {
  614. va_list args;
  615. UINTN back;
  616. va_start (args, fmt);
  617. back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args);
  618. va_end (args);
  619. return back;
  620. }
  621. UINTN
  622. AsciiVSPrint (
  623. OUT CHAR8 *Str,
  624. IN UINTN StrSize,
  625. IN CONST CHAR8 *fmt,
  626. va_list args
  627. )
  628. /*++
  629. Routine Description:
  630. Prints a formatted ascii string to a buffer using a va_list
  631. Arguments:
  632. Str - Output buffer to print the formatted string into
  633. StrSize - Size of Str. String is truncated to this size.
  634. A size of 0 means there is no limit
  635. fmt - The format string
  636. args - va_list
  637. Returns:
  638. String length returned in buffer
  639. --*/
  640. // Use UnicodeVSPrint() and convert back to ASCII
  641. {
  642. CHAR16 *UnicodeStr, *UnicodeFmt;
  643. UINTN i, Len;
  644. UnicodeStr = AllocatePool(StrSize * sizeof(CHAR16));
  645. if (!UnicodeStr)
  646. return 0;
  647. UnicodeFmt = PoolPrint(L"%a", fmt);
  648. if (!UnicodeFmt) {
  649. FreePool(UnicodeStr);
  650. return 0;
  651. }
  652. Len = UnicodeVSPrint(UnicodeStr, StrSize, UnicodeFmt, args);
  653. FreePool(UnicodeFmt);
  654. // The strings are ASCII so just do a plain Unicode conversion
  655. for (i = 0; i < Len; i++)
  656. Str[i] = (CHAR8)UnicodeStr[i];
  657. Str[Len] = 0;
  658. FreePool(UnicodeStr);
  659. return Len;
  660. }
  661. STATIC
  662. VOID
  663. PFLUSH (
  664. IN OUT PRINT_STATE *ps
  665. )
  666. {
  667. *ps->Pos = 0;
  668. if (IsLocalPrint(ps->Output))
  669. ps->Output(ps->Context, ps->Buffer);
  670. else
  671. uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer);
  672. ps->Pos = ps->Buffer;
  673. }
  674. STATIC
  675. VOID
  676. PSETATTR (
  677. IN OUT PRINT_STATE *ps,
  678. IN UINTN Attr
  679. )
  680. {
  681. PFLUSH (ps);
  682. ps->RestoreAttr = ps->Attr;
  683. if (ps->SetAttr) {
  684. uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr);
  685. }
  686. ps->Attr = Attr;
  687. }
  688. STATIC
  689. VOID
  690. PPUTC (
  691. IN OUT PRINT_STATE *ps,
  692. IN CHAR16 c
  693. )
  694. {
  695. // if this is a newline, add a carraige return
  696. if (c == '\n') {
  697. PPUTC (ps, '\r');
  698. }
  699. *ps->Pos = c;
  700. ps->Pos += 1;
  701. ps->Len += 1;
  702. // if at the end of the buffer, flush it
  703. if (ps->Pos >= ps->End) {
  704. PFLUSH(ps);
  705. }
  706. }
  707. STATIC
  708. CHAR16
  709. PGETC (
  710. IN POINTER *p
  711. )
  712. {
  713. CHAR16 c;
  714. c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index];
  715. p->Index += 1;
  716. return c;
  717. }
  718. STATIC
  719. VOID
  720. PITEM (
  721. IN OUT PRINT_STATE *ps
  722. )
  723. {
  724. UINTN Len, i;
  725. PRINT_ITEM *Item;
  726. CHAR16 c;
  727. // Get the length of the item
  728. Item = ps->Item;
  729. Item->Item.Index = 0;
  730. while (Item->Item.Index < Item->FieldWidth) {
  731. c = PGETC(&Item->Item);
  732. if (!c) {
  733. Item->Item.Index -= 1;
  734. break;
  735. }
  736. }
  737. Len = Item->Item.Index;
  738. // if there is no item field width, use the items width
  739. if (Item->FieldWidth == (UINTN) -1) {
  740. Item->FieldWidth = Len;
  741. }
  742. // if item is larger then width, update width
  743. if (Len > Item->Width) {
  744. Item->Width = Len;
  745. }
  746. // if pad field before, add pad char
  747. if (Item->PadBefore) {
  748. for (i=Item->Width; i < Item->FieldWidth; i+=1) {
  749. PPUTC (ps, ' ');
  750. }
  751. }
  752. // pad item
  753. for (i=Len; i < Item->Width; i++) {
  754. PPUTC (ps, Item->Pad);
  755. }
  756. // add the item
  757. Item->Item.Index=0;
  758. while (Item->Item.Index < Len) {
  759. PPUTC (ps, PGETC(&Item->Item));
  760. }
  761. // If pad at the end, add pad char
  762. if (!Item->PadBefore) {
  763. for (i=Item->Width; i < Item->FieldWidth; i+=1) {
  764. PPUTC (ps, ' ');
  765. }
  766. }
  767. }
  768. STATIC
  769. UINTN
  770. _Print (
  771. IN PRINT_STATE *ps
  772. )
  773. /*++
  774. Routine Description:
  775. %w.lF - w = width
  776. l = field width
  777. F = format of arg
  778. Args F:
  779. 0 - pad with zeros
  780. - - justify on left (default is on right)
  781. , - add comma's to field
  782. * - width provided on stack
  783. n - Set output attribute to normal (for this field only)
  784. h - Set output attribute to highlight (for this field only)
  785. e - Set output attribute to error (for this field only)
  786. l - Value is 64 bits
  787. a - ascii string
  788. s - unicode string
  789. X - fixed 8 byte value in hex
  790. x - hex value
  791. d - value as signed decimal
  792. u - value as unsigned decimal
  793. f - value as floating point
  794. c - Unicode char
  795. t - EFI time structure
  796. g - Pointer to GUID
  797. r - EFI status code (result code)
  798. D - pointer to Device Path with normal ending.
  799. N - Set output attribute to normal
  800. H - Set output attribute to highlight
  801. E - Set output attribute to error
  802. % - Print a %
  803. Arguments:
  804. SystemTable - The system table
  805. Returns:
  806. Number of charactors written
  807. --*/
  808. {
  809. CHAR16 c;
  810. UINTN Attr;
  811. PRINT_ITEM Item;
  812. CHAR16 Buffer[PRINT_STRING_LEN];
  813. ps->Len = 0;
  814. ps->Buffer = Buffer;
  815. ps->Pos = Buffer;
  816. ps->End = Buffer + PRINT_STRING_LEN - 1;
  817. ps->Item = &Item;
  818. ps->fmt.Index = 0;
  819. while ((c = PGETC(&ps->fmt))) {
  820. if (c != '%') {
  821. PPUTC ( ps, c );
  822. continue;
  823. }
  824. // setup for new item
  825. Item.FieldWidth = (UINTN) -1;
  826. Item.Width = 0;
  827. Item.WidthParse = &Item.Width;
  828. Item.Pad = ' ';
  829. Item.PadBefore = TRUE;
  830. Item.Comma = FALSE;
  831. Item.Long = FALSE;
  832. Item.Item.Ascii = FALSE;
  833. Item.Item.pw = NULL;
  834. ps->RestoreAttr = 0;
  835. Attr = 0;
  836. while ((c = PGETC(&ps->fmt))) {
  837. switch (c) {
  838. case '%':
  839. //
  840. // %% -> %
  841. //
  842. Item.Scratch[0] = '%';
  843. Item.Scratch[1] = 0;
  844. Item.Item.pw = Item.Scratch;
  845. break;
  846. case ',':
  847. Item.Comma = TRUE;
  848. break;
  849. case '-':
  850. Item.PadBefore = FALSE;
  851. break;
  852. case '*':
  853. *Item.WidthParse = va_arg(ps->args, UINTN);
  854. break;
  855. case '.':
  856. Item.WidthParse = &Item.FieldWidth;
  857. break;
  858. case '0':
  859. Item.Pad = '0';
  860. break;
  861. case '1':
  862. case '2':
  863. case '3':
  864. case '4':
  865. case '5':
  866. case '6':
  867. case '7':
  868. case '8':
  869. case '9':
  870. *Item.WidthParse = 0;
  871. do {
  872. *Item.WidthParse = *Item.WidthParse * 10 + c - '0';
  873. c = PGETC(&ps->fmt);
  874. } while (c >= '0' && c <= '9') ;
  875. ps->fmt.Index -= 1;
  876. break;
  877. case 'a':
  878. Item.Item.pc = va_arg(ps->args, CHAR8 *);
  879. Item.Item.Ascii = TRUE;
  880. if (!Item.Item.pc) {
  881. Item.Item.pc = (CHAR8 *)"(null)";
  882. }
  883. break;
  884. case 'c':
  885. Item.Scratch[0] = (CHAR16) va_arg(ps->args, UINTN);
  886. Item.Scratch[1] = 0;
  887. Item.Item.pw = Item.Scratch;
  888. break;
  889. case 'D':
  890. {
  891. EFI_DEVICE_PATH *dp = va_arg(ps->args, EFI_DEVICE_PATH *);
  892. CHAR16 *dpstr = DevicePathToStr(dp);
  893. StrnCpy(Item.Scratch, dpstr, PRINT_ITEM_BUFFER_LEN);
  894. Item.Scratch[PRINT_ITEM_BUFFER_LEN-1] = L'\0';
  895. FreePool(dpstr);
  896. Item.Item.pw = Item.Scratch;
  897. break;
  898. }
  899. case 'd':
  900. ValueToString (
  901. Item.Scratch,
  902. Item.Comma,
  903. Item.Long ? va_arg(ps->args, INT64) : va_arg(ps->args, INT32)
  904. );
  905. Item.Item.pw = Item.Scratch;
  906. break;
  907. case 'E':
  908. Attr = ps->AttrError;
  909. break;
  910. case 'e':
  911. PSETATTR(ps, ps->AttrError);
  912. break;
  913. case 'f':
  914. FloatToString (
  915. Item.Scratch,
  916. Item.Comma,
  917. va_arg(ps->args, double)
  918. );
  919. Item.Item.pw = Item.Scratch;
  920. break;
  921. case 'g':
  922. GuidToString (Item.Scratch, va_arg(ps->args, EFI_GUID *));
  923. Item.Item.pw = Item.Scratch;
  924. break;
  925. case 'H':
  926. Attr = ps->AttrHighlight;
  927. break;
  928. case 'h':
  929. PSETATTR(ps, ps->AttrHighlight);
  930. break;
  931. case 'l':
  932. Item.Long = TRUE;
  933. break;
  934. case 'N':
  935. Attr = ps->AttrNorm;
  936. break;
  937. case 'n':
  938. PSETATTR(ps, ps->AttrNorm);
  939. break;
  940. case 'r':
  941. StatusToString (Item.Scratch, va_arg(ps->args, EFI_STATUS));
  942. Item.Item.pw = Item.Scratch;
  943. break;
  944. case 's':
  945. Item.Item.pw = va_arg(ps->args, CHAR16 *);
  946. if (!Item.Item.pw) {
  947. Item.Item.pw = L"(null)";
  948. }
  949. break;
  950. case 't':
  951. TimeToString (Item.Scratch, va_arg(ps->args, EFI_TIME *));
  952. Item.Item.pw = Item.Scratch;
  953. break;
  954. case 'u':
  955. ValueToString (
  956. Item.Scratch,
  957. Item.Comma,
  958. Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
  959. );
  960. Item.Item.pw = Item.Scratch;
  961. break;
  962. case 'X':
  963. Item.Width = Item.Long ? 16 : 8;
  964. Item.Pad = '0';
  965. #if __GNUC__ >= 7
  966. __attribute__ ((fallthrough));
  967. #endif
  968. case 'x':
  969. ValueToHex (
  970. Item.Scratch,
  971. Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32)
  972. );
  973. Item.Item.pw = Item.Scratch;
  974. break;
  975. default:
  976. Item.Scratch[0] = '?';
  977. Item.Scratch[1] = 0;
  978. Item.Item.pw = Item.Scratch;
  979. break;
  980. }
  981. // if we have an Item
  982. if (Item.Item.pw) {
  983. PITEM (ps);
  984. break;
  985. }
  986. // if we have an Attr set
  987. if (Attr) {
  988. PSETATTR(ps, Attr);
  989. ps->RestoreAttr = 0;
  990. break;
  991. }
  992. }
  993. if (ps->RestoreAttr) {
  994. PSETATTR(ps, ps->RestoreAttr);
  995. }
  996. }
  997. // Flush buffer
  998. PFLUSH (ps);
  999. return ps->Len;
  1000. }
  1001. STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7',
  1002. '8','9','A','B','C','D','E','F'};
  1003. VOID
  1004. ValueToHex (
  1005. IN CHAR16 *Buffer,
  1006. IN UINT64 v
  1007. )
  1008. {
  1009. CHAR8 str[30], *p1;
  1010. CHAR16 *p2;
  1011. if (!v) {
  1012. Buffer[0] = '0';
  1013. Buffer[1] = 0;
  1014. return ;
  1015. }
  1016. p1 = str;
  1017. p2 = Buffer;
  1018. while (v) {
  1019. // Without the cast, the MSVC compiler may insert a reference to __allmull
  1020. *(p1++) = Hex[(UINTN)(v & 0xf)];
  1021. v = RShiftU64 (v, 4);
  1022. }
  1023. while (p1 != str) {
  1024. *(p2++) = *(--p1);
  1025. }
  1026. *p2 = 0;
  1027. }
  1028. VOID
  1029. ValueToString (
  1030. IN CHAR16 *Buffer,
  1031. IN BOOLEAN Comma,
  1032. IN INT64 v
  1033. )
  1034. {
  1035. STATIC CHAR8 ca[] = { 3, 1, 2 };
  1036. CHAR8 str[40], *p1;
  1037. CHAR16 *p2;
  1038. UINTN c, r;
  1039. if (!v) {
  1040. Buffer[0] = '0';
  1041. Buffer[1] = 0;
  1042. return ;
  1043. }
  1044. p1 = str;
  1045. p2 = Buffer;
  1046. if (v < 0) {
  1047. *(p2++) = '-';
  1048. v = -v;
  1049. }
  1050. while (v) {
  1051. v = (INT64)DivU64x32 ((UINT64)v, 10, &r);
  1052. *(p1++) = (CHAR8)r + '0';
  1053. }
  1054. c = (UINTN) (Comma ? ca[(p1 - str) % 3] : 999) + 1;
  1055. while (p1 != str) {
  1056. c -= 1;
  1057. if (!c) {
  1058. *(p2++) = ',';
  1059. c = 3;
  1060. }
  1061. *(p2++) = *(--p1);
  1062. }
  1063. *p2 = 0;
  1064. }
  1065. VOID
  1066. FloatToString (
  1067. IN CHAR16 *Buffer,
  1068. IN BOOLEAN Comma,
  1069. IN double v
  1070. )
  1071. {
  1072. /*
  1073. * Integer part.
  1074. */
  1075. INTN i = (INTN)v;
  1076. ValueToString(Buffer, Comma, i);
  1077. /*
  1078. * Decimal point.
  1079. */
  1080. UINTN x = StrLen(Buffer);
  1081. Buffer[x] = L'.';
  1082. x++;
  1083. /*
  1084. * Keep fractional part.
  1085. */
  1086. float f = (float)(v - i);
  1087. if (f < 0) f = -f;
  1088. /*
  1089. * Leading fractional zeroes.
  1090. */
  1091. f *= 10.0;
  1092. while ( (f != 0)
  1093. && ((INTN)f == 0))
  1094. {
  1095. Buffer[x] = L'0';
  1096. x++;
  1097. f *= 10.0;
  1098. }
  1099. /*
  1100. * Fractional digits.
  1101. */
  1102. while ((float)(INTN)f != f)
  1103. {
  1104. f *= 10;
  1105. }
  1106. ValueToString(Buffer + x, FALSE, (INTN)f);
  1107. return;
  1108. }
  1109. VOID
  1110. TimeToString (
  1111. OUT CHAR16 *Buffer,
  1112. IN EFI_TIME *Time
  1113. )
  1114. {
  1115. UINTN Hour, Year;
  1116. CHAR16 AmPm;
  1117. AmPm = 'a';
  1118. Hour = Time->Hour;
  1119. if (Time->Hour == 0) {
  1120. Hour = 12;
  1121. } else if (Time->Hour >= 12) {
  1122. AmPm = 'p';
  1123. if (Time->Hour >= 13) {
  1124. Hour -= 12;
  1125. }
  1126. }
  1127. Year = Time->Year % 100;
  1128. // bugbug: for now just print it any old way
  1129. UnicodeSPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c",
  1130. Time->Month,
  1131. Time->Day,
  1132. Year,
  1133. Hour,
  1134. Time->Minute,
  1135. AmPm
  1136. );
  1137. }
  1138. VOID
  1139. DumpHex (
  1140. IN UINTN Indent,
  1141. IN UINTN Offset,
  1142. IN UINTN DataSize,
  1143. IN VOID *UserData
  1144. )
  1145. {
  1146. CHAR8 *Data, Val[50], Str[20], c;
  1147. UINTN Size, Index;
  1148. UINTN ScreenCount;
  1149. UINTN TempColumn;
  1150. UINTN ScreenSize;
  1151. CHAR16 ReturnStr[1];
  1152. uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
  1153. ScreenCount = 0;
  1154. ScreenSize -= 2;
  1155. Data = UserData;
  1156. while (DataSize) {
  1157. Size = 16;
  1158. if (Size > DataSize) {
  1159. Size = DataSize;
  1160. }
  1161. for (Index=0; Index < Size; Index += 1) {
  1162. c = Data[Index];
  1163. Val[Index*3+0] = Hex[c>>4];
  1164. Val[Index*3+1] = Hex[c&0xF];
  1165. Val[Index*3+2] = (Index == 7)?'-':' ';
  1166. Str[Index] = (c < ' ' || c > 'z') ? '.' : c;
  1167. }
  1168. Val[Index*3] = 0;
  1169. Str[Index] = 0;
  1170. Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str);
  1171. Data += Size;
  1172. Offset += Size;
  1173. DataSize -= Size;
  1174. ScreenCount++;
  1175. if (ScreenCount >= ScreenSize && ScreenSize != 0) {
  1176. //
  1177. // If ScreenSize == 0 we have the console redirected so don't
  1178. // block updates
  1179. //
  1180. ScreenCount = 0;
  1181. Print (L"Press Enter to continue :");
  1182. Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
  1183. Print (L"\n");
  1184. }
  1185. }
  1186. }