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