]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei/lprint.c
QuarkSocPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkSocPkg / QuarkNorthCluster / MemoryInit / Pei / lprint.c
1 /** @file
2 Serial conole output and string formating.
3
4 Copyright (c) 2013-2015 Intel Corporation.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9 #include "memory_options.h"
10 #include "general_definitions.h"
11
12 // Resource programmed to PCI bridge, 1MB bound alignment is needed.
13 // The default value is overwritten by MRC parameter, assuming code
14 // relocated to eSRAM.
15 uint32_t UartMmioBase = 0;
16
17 // Serial port registers based on SerialPortLib.c
18 #define R_UART_BAUD_THR 0
19 #define R_UART_LSR 20
20
21 #define B_UART_LSR_RXRDY BIT0
22 #define B_UART_LSR_TXRDY BIT5
23 #define B_UART_LSR_TEMT BIT6
24
25 // Print mask see DPF and D_Xxxx
26 #define DPF_MASK DpfPrintMask
27
28 // Select class of messages enabled for printing
29 uint32_t DpfPrintMask =
30 D_ERROR |
31 D_INFO |
32 // D_REGRD |
33 // D_REGWR |
34 // D_FCALL |
35 // D_TRN |
36 0;
37
38 #ifdef NDEBUG
39 // Don't generate debug code
40 void dpf( uint32_t mask, char_t* bla, ...)
41 {
42 return;
43 }
44
45 uint8_t mgetc(void)
46 {
47 return 0;
48 }
49
50 uint8_t mgetch(void)
51 {
52 return 0;
53 }
54
55 #else
56
57 #ifdef SIM
58 // Use Vpi console in simulation environment
59 #include <vpi_user.h>
60
61 void dpf( uint32_t mask, char_t* bla, ...)
62 {
63 va_list va;
64
65 if( 0 == (mask & DPF_MASK)) return;
66
67 va_start( va, bla);
68 vpi_vprintf( bla, va);
69 va_end(va);
70 }
71
72 #else
73
74 #ifdef EMU
75 // Use standard console in windows environment
76 #include <stdio.h>
77 #endif
78
79 // Read character from serial port
80 uint8_t mgetc(void)
81 {
82 #ifdef EMU
83
84 // Emulation in Windows environment uses console
85 getchar();
86
87 #else
88 uint8_t c;
89
90 while ((*(volatile uint8_t*) (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) == 0);
91 c = *(volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR);
92
93 return c;
94 #endif
95 }
96
97
98 uint8_t mgetch(void)
99 {
100 #ifdef EMU
101 return 0;
102 #else
103 uint8_t c = 0;
104
105 if((*(volatile uint8_t*) (UartMmioBase + R_UART_LSR) & B_UART_LSR_RXRDY) != 0)
106 {
107 c = *(volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR);
108 }
109
110 return c;
111 #endif
112 }
113
114 // Print single character
115 static void printc(
116 uint8_t c)
117 {
118 #ifdef EMU
119
120 // Emulation in Windows environment uses console output
121 putchar(c);
122
123 #else
124
125 //
126 // Use MMIO access to serial port on PCI
127 // while( 0 == (0x20 & inp(0x3f8 + 5)));
128 // outp(0x3f8 + 0, c);
129 //
130 while (0
131 == (B_UART_LSR_TEMT & *((volatile uint8_t*) (UartMmioBase + R_UART_LSR))))
132 ;
133 *((volatile uint8_t*) (UartMmioBase + R_UART_BAUD_THR)) = c;
134 #endif
135 }
136
137 // Print 0 terminated string on serial console
138 static void printstr(
139 char_t *str)
140 {
141 while (*str)
142 {
143 printc(*str++);
144 }
145 }
146 // Print 64bit number as hex string on serial console
147 // the width parameters allows skipping leading zeros
148 static void printhexx(
149 uint64_t val,
150 uint32_t width)
151 {
152 uint32_t i;
153 uint8_t c;
154 uint8_t empty = 1;
155
156 // 64bit number has 16 characters in hex representation
157 for (i = 16; i > 0; i--)
158 {
159 c = *(((uint8_t *)&val) + ((i - 1) >> 1));
160 if (((i - 1) & 1) != 0)
161 c = c >> 4;
162 c = c & 0x0F;
163
164 if (c > 9)
165 c += 'A' - 10;
166 else
167 c += '0';
168
169 if (c != '0')
170 {
171 // end of leading zeros
172 empty = 0;
173 }
174
175 // don't print leading zero
176 if (!empty || i <= width)
177 {
178 printc(c);
179 }
180 }
181 }
182 // Print 32bit number as hex string on serial console
183 // the width parameters allows skipping leading zeros
184 static void printhex(
185 uint32_t val,
186 uint32_t width)
187 {
188 uint32_t i;
189 uint8_t c;
190 uint8_t empty = 1;
191
192 // 32bit number has 8 characters in hex representation
193 for (i = 8; i > 0; i--)
194 {
195 c = (uint8_t) ((val >> 28) & 0x0F);
196 if (c > 9)
197 c += 'A' - 10;
198 else
199 c += '0';
200
201 val = val << 4;
202
203 if (c != '0')
204 {
205 // end of leading zeros
206 empty = 0;
207 }
208
209 // don't print leading zero
210 if (!empty || i <= width)
211 {
212 printc(c);
213 }
214 }
215 }
216 // Print 32bit number as decimal string on serial console
217 // the width parameters allows skipping leading zeros
218 static void printdec(
219 uint32_t val,
220 uint32_t width)
221 {
222 uint32_t i;
223 uint8_t c = 0;
224 uint8_t empty = 1;
225
226 // Ten digits is enough for 32bit number in decimal
227 uint8_t buf[10];
228
229 for (i = 0; i < sizeof(buf); i++)
230 {
231 c = (uint8_t) (val % 10);
232 buf[i] = c + '0';
233 val = val / 10;
234 }
235
236 while (i > 0)
237 {
238 c = buf[--i];
239
240 if (c != '0')
241 {
242 // end of leading zeros
243 empty = 0;
244 }
245
246 // don't print leading zero
247 if (!empty || i < width)
248 {
249 printc(c);
250 }
251 }
252 }
253
254 // Consume numeric substring leading the given string
255 // Return pointer to the first non-numeric character
256 // Buffer reference by width is updated with number
257 // converted from the numeric substring.
258 static char_t *getwidth(
259 char_t *bla,
260 uint32_t *width)
261 {
262 uint32_t val = 0;
263
264 while (*bla >= '0' && *bla <= '9')
265 {
266 val = val * 10 + *bla - '0';
267 bla += 1;
268 }
269
270 if (val > 0)
271 {
272 *width = val;
273 }
274 return bla;
275 }
276
277 // Consume print format designator from the head of given string
278 // Return pointer to first character after format designator
279 // input fmt
280 // ----- ---
281 // s -> s
282 // d -> d
283 // X -> X
284 // llX -> L
285 static char_t *getformat(
286 char_t *bla,
287 uint8_t *fmt)
288 {
289 if (bla[0] == 's')
290 {
291 bla += 1;
292 *fmt = 's';
293 }
294 else if (bla[0] == 'd')
295 {
296 bla += 1;
297 *fmt = 'd';
298 }
299 else if (bla[0] == 'X' || bla[0] == 'x')
300 {
301 bla += 1;
302 *fmt = 'X';
303 }
304 else if (bla[0] == 'l' && bla[1] == 'l' && bla[2] == 'X')
305 {
306 bla += 3;
307 *fmt = 'L';
308 }
309
310 return bla;
311 }
312
313 // Simplified implementation of standard printf function
314 // The output is directed to serial console. Only selected
315 // class of messages is printed (mask has to match DpfPrintMask)
316 // Supported print formats: %[n]s,%[n]d,%[n]X,,%[n]llX
317 // The width is ignored for %s format.
318 void dpf(
319 uint32_t mask,
320 char_t* bla,
321 ...)
322 {
323 uint32_t* arg = (uint32_t*) (&bla + 1);
324
325 // Check UART MMIO base configured
326 if (0 == UartMmioBase)
327 return;
328
329 // Check event not masked
330 if (0 == (mask & DPF_MASK))
331 return;
332
333 for (;;)
334 {
335 uint8_t x = *bla++;
336 if (x == 0)
337 break;
338
339 if (x == '\n')
340 {
341 printc('\r');
342 printc('\n');
343 }
344 else if (x == '%')
345 {
346 uint8_t fmt = 0;
347 uint32_t width = 1;
348
349 bla = getwidth(bla, &width);
350 bla = getformat(bla, &fmt);
351
352 // Print value
353 if (fmt == 'd')
354 {
355 printdec(*arg, width);
356 arg += 1;
357 }
358 else if (fmt == 'X')
359 {
360 printhex(*arg, width);
361 arg += 1;
362 }
363 else if (fmt == 'L')
364 {
365 printhexx(*(uint64_t*) arg, width);
366 arg += 2;
367 }
368 else if (fmt == 's')
369 {
370 printstr(*(char**) arg);
371 arg += 1;
372 }
373 }
374 else
375 {
376 printc(x);
377 }
378 }
379 }
380
381 #endif //SIM
382 #endif //NDEBUG