mxs_nand: Update compatible string for i.MX6SX
[oweals/u-boot.git] / 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_text_input_protocol *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  * @prec:       minimum number of digits to display
75  * @buf:        pointer to buffer address
76  *              on return position of terminating zero word
77  */
78 static void uint2dec(u32 value, int prec, 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 || 10 - i <= prec)
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  * @prec:       minimum number of digits to display
115  * @buf:        pointer to buffer address
116  * on return position of terminating zero word
117  */
118 static void int2dec(s32 value, int prec, u16 **buf)
119 {
120         u32 u;
121         u16 *pos = *buf;
122
123         if (value < 0) {
124                 *pos++ = '-';
125                 u = -value;
126         } else {
127                 u = value;
128         }
129         uint2dec(u, prec, &pos);
130         *buf = pos;
131 }
132
133 /*
134  * Print a colored formatted string to the EFI console
135  *
136  * @color       color, see constants in efi_api.h, use -1 for no color
137  * @fmt         format string
138  * @...         optional arguments
139  */
140 void efi_st_printc(int color, const char *fmt, ...)
141 {
142         va_list args;
143         u16 buf[160];
144         const char *c;
145         u16 *pos = buf;
146         const char *s;
147         u16 *u;
148         int prec;
149
150         va_start(args, fmt);
151
152         if (color >= 0)
153                 con_out->set_attribute(con_out, (unsigned long)color);
154         c = fmt;
155         for (; *c; ++c) {
156                 switch (*c) {
157                 case '\\':
158                         ++c;
159                         switch (*c) {
160                         case '\0':
161                                 --c;
162                                 break;
163                         case 'n':
164                                 *pos++ = '\n';
165                                 break;
166                         case 'r':
167                                 *pos++ = '\r';
168                                 break;
169                         case 't':
170                                 *pos++ = '\t';
171                                 break;
172                         default:
173                                 *pos++ = *c;
174                         }
175                         break;
176                 case '%':
177                         ++c;
178                         /* Parse precision */
179                         if (*c == '.') {
180                                 ++c;
181                                 prec = *c - '0';
182                                 ++c;
183                         } else {
184                                 prec = 0;
185                         }
186                         switch (*c) {
187                         case '\0':
188                                 --c;
189                                 break;
190                         case 'd':
191                                 int2dec(va_arg(args, s32), prec, &pos);
192                                 break;
193                         case 'p':
194                                 ++c;
195                                 switch (*c) {
196                                 /* MAC address */
197                                 case 'm':
198                                         mac(va_arg(args, void*), &pos);
199                                         break;
200
201                                 /* u16 string */
202                                 case 's':
203                                         u = va_arg(args, u16*);
204                                         if (pos > buf) {
205                                                 *pos = 0;
206                                                 con_out->output_string(con_out,
207                                                                        buf);
208                                         }
209                                         con_out->output_string(con_out, u);
210                                         pos = buf;
211                                         break;
212                                 default:
213                                         --c;
214                                         pointer(va_arg(args, void*), &pos);
215                                 }
216                                 break;
217                         case 's':
218                                 s = va_arg(args, const char *);
219                                 for (; *s; ++s)
220                                         *pos++ = *s;
221                                 break;
222                         case 'u':
223                                 uint2dec(va_arg(args, u32), prec, &pos);
224                                 break;
225                         default:
226                                 break;
227                         }
228                         break;
229                 default:
230                         *pos++ = *c;
231                 }
232         }
233         va_end(args);
234         *pos = 0;
235         con_out->output_string(con_out, buf);
236         if (color >= 0)
237                 con_out->set_attribute(con_out, EFI_LIGHTGRAY);
238 }
239
240 /*
241  * Reads an Unicode character from the input device.
242  *
243  * @return: Unicode character
244  */
245 u16 efi_st_get_key(void)
246 {
247         struct efi_input_key input_key;
248         efi_status_t ret;
249
250         /* Wait for next key */
251         do {
252                 ret = con_in->read_key_stroke(con_in, &input_key);
253         } while (ret == EFI_NOT_READY);
254         return input_key.unicode_char;
255 }