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