efi_selftest_console.c 4.8 KB

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