efi_selftest_console.c 5.2 KB

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