Updates to Freedom SoCs
[freedom-sifive.git] / bootrom / sdboot / kprintf.c
1 // See LICENSE for license details.
2 #include <stdarg.h>
3 #include <stdint.h>
4 #include <stdbool.h>
5
6 #include "kprintf.h"
7
8 static inline void _kputs(const char *s)
9 {
10 char c;
11 for (; (c = *s) != '\0'; s++)
12 kputc(c);
13 }
14
15 void kputs(const char *s)
16 {
17 _kputs(s);
18 kputc('\r');
19 kputc('\n');
20 }
21
22 void kprintf(const char *fmt, ...)
23 {
24 va_list vl;
25 bool is_format, is_long, is_char;
26 char c;
27
28 va_start(vl, fmt);
29 is_format = false;
30 is_long = false;
31 is_char = false;
32 while ((c = *fmt++) != '\0') {
33 if (is_format) {
34 switch (c) {
35 case 'l':
36 is_long = true;
37 continue;
38 case 'h':
39 is_char = true;
40 continue;
41 case 'x': {
42 unsigned long n;
43 long i;
44 if (is_long) {
45 n = va_arg(vl, unsigned long);
46 i = (sizeof(unsigned long) << 3) - 4;
47 } else {
48 n = va_arg(vl, unsigned int);
49 i = is_char ? 4 : (sizeof(unsigned int) << 3) - 4;
50 }
51 for (; i >= 0; i -= 4) {
52 long d;
53 d = (n >> i) & 0xF;
54 kputc(d < 10 ? '0' + d : 'a' + d - 10);
55 }
56 break;
57 }
58 case 's':
59 _kputs(va_arg(vl, const char *));
60 break;
61 case 'c':
62 kputc(va_arg(vl, int));
63 break;
64 }
65 is_format = false;
66 is_long = false;
67 is_char = false;
68 } else if (c == '%') {
69 is_format = true;
70 } else {
71 kputc(c);
72 }
73 }
74 va_end(vl);
75 }