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