efi_selftest_console.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * EFI efi_selftest
  3. *
  4. * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <efi_selftest.h>
  9. #include <vsprintf.h>
  10. struct efi_simple_text_output_protocol *con_out;
  11. struct efi_simple_input_interface *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. * Print a pointer to an u16 string
  43. *
  44. * @pointer: pointer
  45. * @buf: pointer to buffer address
  46. * on return position of terminating zero word
  47. */
  48. static void pointer(void *pointer, u16 **buf)
  49. {
  50. int i;
  51. u16 c;
  52. uintptr_t p = (uintptr_t)pointer;
  53. u16 *pos = *buf;
  54. for (i = 8 * sizeof(p) - 4; i >= 0; i -= 4) {
  55. c = (p >> i) & 0x0f;
  56. c += '0';
  57. if (c > '9')
  58. c += 'a' - '9' - 1;
  59. *pos++ = c;
  60. }
  61. *pos = 0;
  62. *buf = pos;
  63. }
  64. /*
  65. * Print an unsigned 32bit value as decimal number to an u16 string
  66. *
  67. * @value: value to be printed
  68. * @buf: pointer to buffer address
  69. * on return position of terminating zero word
  70. */
  71. static void uint2dec(u32 value, u16 **buf)
  72. {
  73. u16 *pos = *buf;
  74. int i;
  75. u16 c;
  76. u64 f;
  77. /*
  78. * Increment by .5 and multiply with
  79. * (2 << 60) / 1,000,000,000 = 0x44B82FA0.9B5A52CC
  80. * to move the first digit to bit 60-63.
  81. */
  82. f = 0x225C17D0;
  83. f += (0x9B5A52DULL * value) >> 28;
  84. f += 0x44B82FA0ULL * value;
  85. for (i = 0; i < 10; ++i) {
  86. /* Write current digit */
  87. c = f >> 60;
  88. if (c || pos != *buf)
  89. *pos++ = c + '0';
  90. /* Eliminate current digit */
  91. f &= 0xfffffffffffffff;
  92. /* Get next digit */
  93. f *= 0xaULL;
  94. }
  95. if (pos == *buf)
  96. *pos++ = '0';
  97. *pos = 0;
  98. *buf = pos;
  99. }
  100. /*
  101. * Print a signed 32bit value as decimal number to an u16 string
  102. *
  103. * @value: value to be printed
  104. * @buf: pointer to buffer address
  105. * on return position of terminating zero word
  106. */
  107. static void int2dec(s32 value, u16 **buf)
  108. {
  109. u32 u;
  110. u16 *pos = *buf;
  111. if (value < 0) {
  112. *pos++ = '-';
  113. u = -value;
  114. } else {
  115. u = value;
  116. }
  117. uint2dec(u, &pos);
  118. *buf = pos;
  119. }
  120. /*
  121. * Print a formatted string to the EFI console
  122. *
  123. * @fmt: format string
  124. * @...: optional arguments
  125. */
  126. void efi_st_printf(const char *fmt, ...)
  127. {
  128. va_list args;
  129. u16 buf[160];
  130. const char *c;
  131. u16 *pos = buf;
  132. const char *s;
  133. va_start(args, fmt);
  134. c = fmt;
  135. for (; *c; ++c) {
  136. switch (*c) {
  137. case '\\':
  138. ++c;
  139. switch (*c) {
  140. case '\0':
  141. --c;
  142. break;
  143. case 'n':
  144. *pos++ = '\n';
  145. break;
  146. case 'r':
  147. *pos++ = '\r';
  148. break;
  149. case 't':
  150. *pos++ = '\t';
  151. break;
  152. default:
  153. *pos++ = *c;
  154. }
  155. break;
  156. case '%':
  157. ++c;
  158. switch (*c) {
  159. case '\0':
  160. --c;
  161. break;
  162. case 'd':
  163. int2dec(va_arg(args, s32), &pos);
  164. break;
  165. case 'p':
  166. ++c;
  167. switch (*c) {
  168. case 'm':
  169. mac(va_arg(args, void*), &pos);
  170. break;
  171. default:
  172. --c;
  173. pointer(va_arg(args, void*), &pos);
  174. }
  175. break;
  176. case 's':
  177. s = va_arg(args, const char *);
  178. for (; *s; ++s)
  179. *pos++ = *s;
  180. break;
  181. case 'u':
  182. uint2dec(va_arg(args, u32), &pos);
  183. break;
  184. default:
  185. break;
  186. }
  187. break;
  188. default:
  189. *pos++ = *c;
  190. }
  191. }
  192. va_end(args);
  193. *pos = 0;
  194. con_out->output_string(con_out, buf);
  195. }
  196. /*
  197. * Reads an Unicode character from the input device.
  198. *
  199. * @return: Unicode character
  200. */
  201. u16 efi_st_get_key(void)
  202. {
  203. struct efi_input_key input_key;
  204. efi_status_t ret;
  205. /* Wait for next key */
  206. do {
  207. ret = con_in->read_key_stroke(con_in, &input_key);
  208. } while (ret == EFI_NOT_READY);
  209. return input_key.unicode_char;
  210. }