• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #include <io/uart.h>
14 #include <lib/printk.h>
15 #include <common/types.h>
16 
17 #define PRINT_BUF_LEN 64
18 
19 typedef __builtin_va_list va_list;
20 #define va_start(v, l) __builtin_va_start(v, l)
21 #define va_end(v)      __builtin_va_end(v)
22 #define va_arg(v, l)   __builtin_va_arg(v, l)
23 #define va_copy(d, s)  __builtin_va_copy(d, s)
24 
25 graphic_putc_handler graphic_putc = NULL;
set_graphic_putc_handler(graphic_putc_handler f)26 void set_graphic_putc_handler(graphic_putc_handler f)
27 {
28     graphic_putc = f;
29 }
30 
simple_outputchar(char ** str,char c)31 static void simple_outputchar(char **str, char c)
32 {
33     if (str) {
34         **str = c;
35         ++(*str);
36     } else {
37         uart_send(c);
38         if (graphic_putc)
39             graphic_putc(c);
40     }
41 }
42 
43 enum flags { PAD_ZERO = 1, PAD_RIGHT = 2 };
44 
prints(char ** out,const char * string,int width,int flags)45 static int prints(char **out, const char *string, int width, int flags)
46 {
47     int pc = 0, padchar = ' ';
48 
49     if (width > 0) {
50         int len = 0;
51         const char *ptr;
52         for (ptr = string; *ptr; ++ptr)
53             ++len;
54         if (len >= width)
55             width = 0;
56         else
57             width -= len;
58         if (flags & PAD_ZERO)
59             padchar = '0';
60     }
61     if (!(flags & PAD_RIGHT)) {
62         for (; width > 0; --width) {
63             simple_outputchar(out, padchar);
64             ++pc;
65         }
66     }
67     for (; *string; ++string) {
68         simple_outputchar(out, *string);
69         ++pc;
70     }
71     for (; width > 0; --width) {
72         simple_outputchar(out, padchar);
73         ++pc;
74     }
75 
76     return pc;
77 }
78 
simple_outputi(char ** out,long i,int base,int sign,int width,int flags,int letbase)79 static int simple_outputi(char **out, long i, int base, int sign, int width,
80                           int flags, int letbase)
81 {
82     char print_buf[PRINT_BUF_LEN];
83     char *s;
84     int t, neg = 0, pc = 0;
85     unsigned long u = i;
86 
87     if (i == 0) {
88         print_buf[0] = '0';
89         print_buf[1] = '\0';
90         return prints(out, print_buf, width, flags);
91     }
92 
93     if (sign && base == 10 && i < 0) {
94         neg = 1;
95         u = -i;
96     }
97 
98     s = print_buf + PRINT_BUF_LEN - 1;
99     *s = '\0';
100 
101     while (u) {
102         t = u % base;
103         if (t >= 10)
104             t += letbase - '0' - 10;
105         *--s = t + '0';
106         u /= base;
107     }
108 
109     if (neg) {
110         if (width && (flags & PAD_ZERO)) {
111             simple_outputchar(out, '-');
112             ++pc;
113             --width;
114         } else {
115             *--s = '-';
116         }
117     }
118 
119     return pc + prints(out, s, width, flags);
120 }
121 
simple_vsprintf(char ** out,const char * format,va_list ap)122 static int simple_vsprintf(char **out, const char *format, va_list ap)
123 {
124     int width, flags;
125     int pc = 0;
126     char scr[2];
127     union {
128         char c;
129         char *s;
130         int i;
131         unsigned int u;
132         long li;
133         unsigned long lu;
134         long long lli;
135         unsigned long long llu;
136         short hi;
137         unsigned short hu;
138         signed char hhi;
139         unsigned char hhu;
140         void *p;
141     } u;
142 
143     for (; *format != 0; ++format) {
144         if (*format == '%') {
145             ++format;
146             width = flags = 0;
147             if (*format == '\0')
148                 break;
149             if (*format == '%')
150                 goto out;
151             if (*format == '-') {
152                 ++format;
153                 flags = PAD_RIGHT;
154             }
155             while (*format == '0') {
156                 ++format;
157                 flags |= PAD_ZERO;
158             }
159             if (*format == '*') {
160                 width = va_arg(ap, int);
161                 format++;
162             } else {
163                 for (; *format >= '0' && *format <= '9'; ++format) {
164                     width *= 10;
165                     width += *format - '0';
166                 }
167             }
168             switch (*format) {
169             case ('d'):
170                 u.i = va_arg(ap, int);
171                 pc += simple_outputi(out, u.i, 10, 1, width, flags, 'a');
172                 break;
173 
174             case ('b'):
175                 u.i = va_arg(ap, int);
176                 pc += simple_outputi(out, u.i, 2, 1, width, flags, 'a');
177                 break;
178 
179             case ('u'):
180                 u.u = va_arg(ap, unsigned int);
181                 pc += simple_outputi(out, u.u, 10, 0, width, flags, 'a');
182                 break;
183 
184             case ('p'):
185                 u.llu = va_arg(ap, unsigned long);
186                 pc += simple_outputi(out, u.llu, 16, 0, width, flags, 'a');
187                 break;
188 
189             case ('x'):
190                 u.u = va_arg(ap, unsigned int);
191                 pc += simple_outputi(out, u.u, 16, 0, width, flags, 'a');
192                 break;
193 
194             case ('X'):
195                 u.u = va_arg(ap, unsigned int);
196                 pc += simple_outputi(out, u.u, 16, 0, width, flags, 'A');
197                 break;
198 
199             case ('c'):
200                 u.c = va_arg(ap, int);
201                 scr[0] = u.c;
202                 scr[1] = '\0';
203                 pc += prints(out, scr, width, flags);
204                 break;
205 
206             case ('s'):
207                 u.s = va_arg(ap, char *);
208                 pc += prints(out, u.s ? u.s : "(null)", width, flags);
209                 break;
210             case ('l'):
211                 ++format;
212                 switch (*format) {
213                 case ('d'):
214                     u.li = va_arg(ap, long);
215                     pc += simple_outputi(out, u.li, 10, 1, width, flags, 'a');
216                     break;
217 
218                 case ('u'):
219                     u.lu = va_arg(ap, unsigned long);
220                     pc += simple_outputi(out, u.lu, 10, 0, width, flags, 'a');
221                     break;
222 
223                 case ('x'):
224                     u.lu = va_arg(ap, unsigned long);
225                     pc += simple_outputi(out, u.lu, 16, 0, width, flags, 'a');
226                     break;
227 
228                 case ('X'):
229                     u.lu = va_arg(ap, unsigned long);
230                     pc += simple_outputi(out, u.lu, 16, 0, width, flags, 'A');
231                     break;
232 
233                 case ('l'):
234                     ++format;
235                     switch (*format) {
236                     case ('d'):
237                         u.lli = va_arg(ap, long long);
238                         pc += simple_outputi(
239                             out, u.lli, 10, 1, width, flags, 'a');
240                         break;
241 
242                     case ('u'):
243                         u.llu = va_arg(ap, unsigned long long);
244                         pc += simple_outputi(
245                             out, u.llu, 10, 0, width, flags, 'a');
246                         break;
247 
248                     case ('x'):
249                         u.llu = va_arg(ap, unsigned long long);
250                         pc += simple_outputi(
251                             out, u.llu, 16, 0, width, flags, 'a');
252                         break;
253 
254                     case ('X'):
255                         u.llu = va_arg(ap, unsigned long long);
256                         pc += simple_outputi(
257                             out, u.llu, 16, 0, width, flags, 'A');
258                         break;
259 
260                     default:
261                         break;
262                     }
263                     break;
264                 default:
265                     break;
266                 }
267                 break;
268             case ('h'):
269                 ++format;
270                 switch (*format) {
271                 case ('d'):
272                     u.hi = va_arg(ap, int);
273                     pc += simple_outputi(out, u.hi, 10, 1, width, flags, 'a');
274                     break;
275 
276                 case ('u'):
277                     u.hu = va_arg(ap, unsigned int);
278                     pc += simple_outputi(out, u.lli, 10, 0, width, flags, 'a');
279                     break;
280 
281                 case ('x'):
282                     u.hu = va_arg(ap, unsigned int);
283                     pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'a');
284                     break;
285 
286                 case ('X'):
287                     u.hu = va_arg(ap, unsigned int);
288                     pc += simple_outputi(out, u.lli, 16, 0, width, flags, 'A');
289                     break;
290 
291                 case ('h'):
292                     ++format;
293                     switch (*format) {
294                     case ('d'):
295                         u.hhi = va_arg(ap, int);
296                         pc += simple_outputi(
297                             out, u.hhi, 10, 1, width, flags, 'a');
298                         break;
299 
300                     case ('u'):
301                         u.hhu = va_arg(ap, unsigned int);
302                         pc += simple_outputi(
303                             out, u.lli, 10, 0, width, flags, 'a');
304                         break;
305 
306                     case ('x'):
307                         u.hhu = va_arg(ap, unsigned int);
308                         pc += simple_outputi(
309                             out, u.lli, 16, 0, width, flags, 'a');
310                         break;
311 
312                     case ('X'):
313                         u.hhu = va_arg(ap, unsigned int);
314                         pc += simple_outputi(
315                             out, u.lli, 16, 0, width, flags, 'A');
316                         break;
317 
318                     default:
319                         break;
320                     }
321                     break;
322                 default:
323                     break;
324                 }
325                 break;
326             default:
327                 break;
328             }
329         } else {
330         out:
331             if (*format == '\n')
332                 simple_outputchar(out, '\r');
333             simple_outputchar(out, *format);
334             ++pc;
335         }
336     }
337     if (out)
338         **out = '\0';
339     return pc;
340 }
341 
simple_sprintf(char * str,const char * fmt,...)342 int simple_sprintf(char *str, const char *fmt, ...)
343 {
344     va_list va;
345     int count;
346 
347     va_start(va, fmt);
348     count = simple_vsprintf(&str, fmt, va);
349     va_end(va);
350 
351     return count;
352 }
353 
354 #define BUF_SIZE 512
355 extern bool is_tlogger_on(void);
356 extern int append_chcore_log(const char *str, size_t len, bool is_kernel);
357 
printk(const char * fmt,...)358 void printk(const char *fmt, ...)
359 {
360     va_list va;
361 
362     if (is_tlogger_on()) {
363         char buf[BUF_SIZE];
364         int count;
365         char *ptr = buf;
366 
367         va_start(va, fmt);
368         count = simple_vsprintf(&ptr, fmt, va);
369         va_end(va);
370         append_chcore_log(buf, count, true);
371         return;
372     }
373 
374     va_start(va, fmt);
375     simple_vsprintf(NULL, fmt, va);
376     va_end(va);
377 }
378