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