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