efi_selftest_console.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * EFI efi_selftest
  4. *
  5. * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. */
  7. #include <efi_selftest.h>
  8. #include <net.h>
  9. #include <vsprintf.h>
  10. struct efi_simple_text_output_protocol *con_out;
  11. struct efi_simple_text_input_protocol *con_in;
  12. /*
  13. * Print a MAC address to an u16 string
  14. *
  15. * @pointer: mac address
  16. * @buf: pointer to buffer address
  17. * on return position of terminating zero word
  18. */
  19. static void mac(void *pointer, u16 **buf)
  20. {
  21. int i, j;
  22. u16 c;
  23. u8 *p = (u8 *)pointer;
  24. u8 byte;
  25. u16 *pos = *buf;
  26. for (i = 0; i < ARP_HLEN; ++i) {
  27. if (i)
  28. *pos++ = ':';
  29. byte = p[i];
  30. for (j = 4; j >= 0; j -= 4) {
  31. c = (byte >> j) & 0x0f;
  32. c += '0';
  33. if (c > '9')
  34. c += 'a' - '9' - 1;
  35. *pos++ = c;
  36. }
  37. }
  38. *pos = 0;
  39. *buf = pos;
  40. }
  41. /*
  42. * printx() - print hexadecimal number to an u16 string
  43. *
  44. * @p: value to print
  45. * @prec: minimum number of digits to print
  46. * @buf: pointer to buffer address,
  47. * on return position of terminating zero word
  48. */
  49. static void printx(u64 p, int prec, u16 **buf)
  50. {
  51. int i;
  52. u16 c;
  53. u16 *pos = *buf;
  54. for (i = 2 * sizeof(p) - 1; i >= 0; --i) {
  55. c = (p >> (4 * i)) & 0x0f;
  56. if (c || pos != *buf || !i || i < prec) {
  57. c += '0';
  58. if (c > '9')
  59. c += 'a' - '9' - 1;
  60. *pos++ = c;
  61. }
  62. }
  63. *pos = 0;
  64. *buf = pos;
  65. }
  66. /*
  67. * Print an unsigned 32bit value as decimal number to an u16 string
  68. *
  69. * @value: value to be printed
  70. * @prec: minimum number of digits to display
  71. * @buf: pointer to buffer address
  72. * on return position of terminating zero word
  73. */
  74. static void uint2dec(u32 value, int prec, u16 **buf)
  75. {
  76. u16 *pos = *buf;
  77. int i;
  78. u16 c;
  79. u64 f;
  80. /*
  81. * Increment by .5 and multiply with
  82. * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
  83. * to move the first digit to bit 60-63.
  84. */
  85. f = 0x225C17D0;
  86. f += (0x9B5A52DULL * value) >> 28;
  87. f += 0x44B82FA0ULL * value;
  88. for (i = 0; i < 10; ++i) {
  89. /* Write current digit */
  90. c = f >> 60;
  91. if (c || pos != *buf || 10 - i <= prec)
  92. *pos++ = c + '0';
  93. /* Eliminate current digit */
  94. f &= 0xfffffffffffffff;
  95. /* Get next digit */
  96. f *= 0xaULL;
  97. }
  98. if (pos == *buf)
  99. *pos++ = '0';
  100. *pos = 0;
  101. *buf = pos;
  102. }
  103. /*
  104. * Print a signed 32bit value as decimal number to an u16 string
  105. *
  106. * @value: value to be printed
  107. * @prec: minimum number of digits to display
  108. * @buf: pointer to buffer address
  109. * on return position of terminating zero word
  110. */
  111. static void int2dec(s32 value, int prec, u16 **buf)
  112. {
  113. u32 u;
  114. u16 *pos = *buf;
  115. if (value < 0) {
  116. *pos++ = '-';
  117. u = -value;
  118. } else {
  119. u = value;
  120. }
  121. uint2dec(u, prec, &pos);
  122. *buf = pos;
  123. }
  124. /*
  125. * Print a colored formatted string to the EFI console
  126. *
  127. * @color color, see constants in efi_api.h, use -1 for no color
  128. * @fmt format string
  129. * @... optional arguments
  130. */
  131. void efi_st_printc(int color, const char *fmt, ...)
  132. {
  133. va_list args;
  134. u16 buf[160];
  135. const char *c;
  136. u16 *pos = buf;
  137. const char *s;
  138. u16 *u;
  139. int prec;
  140. va_start(args, fmt);
  141. if (color >= 0)
  142. con_out->set_attribute(con_out, (unsigned long)color);
  143. c = fmt;
  144. for (; *c; ++c) {
  145. switch (*c) {
  146. case '\\':
  147. ++c;
  148. switch (*c) {
  149. case '\0':
  150. --c;
  151. break;
  152. case 'n':
  153. *pos++ = '\n';
  154. break;
  155. case 'r':
  156. *pos++ = '\r';
  157. break;
  158. case 't':
  159. *pos++ = '\t';
  160. break;
  161. default:
  162. *pos++ = *c;
  163. }
  164. break;
  165. case '%':
  166. ++c;
  167. /* Parse precision */
  168. if (*c == '.') {
  169. ++c;
  170. prec = *c - '0';
  171. ++c;
  172. } else {
  173. prec = 0;
  174. }
  175. switch (*c) {
  176. case '\0':
  177. --c;
  178. break;
  179. case 'd':
  180. int2dec(va_arg(args, s32), prec, &pos);
  181. break;
  182. case 'p':
  183. ++c;
  184. switch (*c) {
  185. /* MAC address */
  186. case 'm':
  187. mac(va_arg(args, void*), &pos);
  188. break;
  189. /* u16 string */
  190. case 's':
  191. u = va_arg(args, u16*);
  192. if (pos > buf) {
  193. *pos = 0;
  194. con_out->output_string(con_out,
  195. buf);
  196. }
  197. con_out->output_string(con_out, u);
  198. pos = buf;
  199. break;
  200. default:
  201. --c;
  202. printx((uintptr_t)va_arg(args, void *),
  203. 2 * sizeof(void *), &pos);
  204. break;
  205. }
  206. break;
  207. case 's':
  208. s = va_arg(args, const char *);
  209. for (; *s; ++s)
  210. *pos++ = *s;
  211. break;
  212. case 'u':
  213. uint2dec(va_arg(args, u32), prec, &pos);
  214. break;
  215. case 'x':
  216. printx((u64)va_arg(args, unsigned int),
  217. prec, &pos);
  218. break;
  219. default:
  220. break;
  221. }
  222. break;
  223. default:
  224. *pos++ = *c;
  225. }
  226. }
  227. va_end(args);
  228. *pos = 0;
  229. con_out->output_string(con_out, buf);
  230. if (color >= 0)
  231. con_out->set_attribute(con_out, EFI_LIGHTGRAY);
  232. }
  233. /*
  234. * Reads an Unicode character from the input device.
  235. *
  236. * @return: Unicode character
  237. */
  238. u16 efi_st_get_key(void)
  239. {
  240. struct efi_input_key input_key;
  241. efi_status_t ret;
  242. /* Wait for next key */
  243. do {
  244. ret = con_in->read_key_stroke(con_in, &input_key);
  245. } while (ret == EFI_NOT_READY);
  246. return input_key.unicode_char;
  247. }