source: trunk/kernel/kern/printk.c @ 445

Last change on this file since 445 was 445, checked in by alain, 6 years ago

Restructure the mini_libc.

File size: 15.1 KB
Line 
1/*
2 * printk.c - Kernel Log & debug messages API implementation.
3 *
4 * authors  Alain Greiner (2016,2017,2018)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH..
9 *
10 * ALMOS-MKH. is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH. is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH.; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_types.h>
25#include <hal_irqmask.h>
26#include <hal_special.h>
27#include <dev_txt.h>
28#include <remote_spinlock.h>
29#include <cluster.h>
30#include <chdev.h>
31#include <printk.h>
32#include <shared_syscalls.h>
33
34///////////////////////////////////////////////////////////////////////////////////
35//      Extern variables
36///////////////////////////////////////////////////////////////////////////////////
37
38extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c
39
40/////////////////////////////////////
41uint32_t snprintf( char     * string,
42                   uint32_t   length,
43                   char     * format, ... )
44{
45
46#define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
47
48    va_list    args;      // printf arguments
49    uint32_t   ps;        // write pointer to the string buffer
50
51    ps = 0;   
52    va_start( args , format );
53
54xprintf_text:
55
56    while ( *format != 0 ) 
57    {
58
59        if (*format == '%')   // copy argument to string
60        {
61            format++;
62            goto xprintf_arguments;
63        }
64        else                  // copy one char to string
65        {
66            TO_STREAM( *format );
67            format++;
68        }
69    }
70
71    va_end( args );
72   
73    // add terminating NUL chracter
74    TO_STREAM( 0 );
75    return ps;
76
77xprintf_arguments:
78
79    {
80        char              buf[30];    // buffer to display one number
81        char *            pbuf;       // pointer on first char to display
82        uint32_t          len = 0;    // number of char to display
83        static const char HexaTab[] = "0123456789ABCDEF";
84        uint32_t          i;
85       
86        // Ignore fields width and precision
87        for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ );
88
89        switch (*format) 
90        {
91            case ('c'):             // char conversion
92            {
93                int val = va_arg( args, int );
94                buf[0] = val;
95                pbuf   = buf;
96                len    = 1;
97                break;
98            }
99            case ('d'):             // decimal signed integer
100            {
101                int val = va_arg( args, int );
102                if (val < 0) 
103                {
104                    TO_STREAM( '-' );
105                    val = -val;
106                }
107                for(i = 0; i < 10; i++) 
108                {
109
110                    buf[9 - i] = HexaTab[val % 10];
111                    if (!(val /= 10)) break;
112                }
113                len =  i + 1;
114                pbuf = &buf[9 - i];
115                break;
116            }
117            case ('u'):             // decimal unsigned integer
118            {
119                uint32_t val = va_arg( args, uint32_t );
120                for(i = 0; i < 10; i++) 
121                {
122                    buf[9 - i] = HexaTab[val % 10];
123                    if (!(val /= 10)) break;
124                }
125                len =  i + 1;
126                pbuf = &buf[9 - i];
127                break;
128            }
129            case ('x'):             // 32 bits hexadecimal
130            case ('l'):             // 64 bits hexadecimal
131            {
132                uint32_t imax;
133                uint64_t val;
134               
135                if ( *format == 'l' )   // 64 bits
136                {
137                    val = va_arg( args, uint64_t);
138                    imax = 16;
139                }
140                else                    // 32 bits
141                {
142                    val = va_arg( args, uint32_t);
143                    imax = 8;
144                }
145               
146                TO_STREAM( '0' );
147                TO_STREAM( 'x' );
148               
149                for(i = 0; i < imax; i++) 
150                {
151                    buf[(imax-1) - i] = HexaTab[val % 16];
152                    if (!(val /= 16))  break;
153                }
154                len =  i + 1;
155                pbuf = &buf[(imax-1) - i];
156                break;
157            }
158            case ('X'):             // 32 bits hexadecimal on 8 characters
159            {
160                uint32_t val = va_arg( args , uint32_t );
161                for(i = 0; i < 8; i++) 
162                {
163                    buf[7 - i] = HexaTab[val % 16];
164                    val = (val>>4);
165                }
166                len =  8;
167                pbuf = buf;
168                break;
169            }
170            case ('s'):             /* string */
171            {
172                char* str = va_arg( args, char* );
173                while (str[len]) { len++; }
174                pbuf = str;
175                break;
176            }
177            default:       // unsupported argument type
178            {
179                return -1;
180            }
181        }  // end switch on  argument type
182
183        format++;
184
185        // copy argument to string
186        for( i = 0 ; i < len ; i++ )
187        {
188            TO_STREAM( pbuf[i] );
189        }
190       
191        goto xprintf_text;
192    }
193} // end snprintf()
194
195//////////////////////////////////////////////////////////////////////////////////////
196// This static function is called by printk(), assert() and nolock_printk()
197// to display a formated string on TXT0, using a busy waiting policy.
198//////////////////////////////////////////////////////////////////////////////////////
199// @ format    : printf like format.
200// @ args      : va_list of arguments.
201//////////////////////////////////////////////////////////////////////////////////////
202static void kernel_printf( char     * format, 
203                           va_list  * args ) 
204{
205
206printf_text:
207
208    while (*format) 
209    {
210        uint32_t i;
211        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
212        if (i) 
213        {
214            dev_txt_sync_write( format, i );
215            format += i;
216        }
217        if (*format == '%') 
218        {
219            format++;
220            goto printf_arguments;
221        }
222    }
223
224    return;
225
226printf_arguments:
227
228    {
229        char      buf[20];
230        char    * pbuf = NULL;
231        uint32_t  len  = 0;
232        static const char HexaTab[] = "0123456789ABCDEF";
233        uint32_t i;
234
235        switch (*format++) 
236        {
237            case ('c'):             /* char conversion */
238            {
239                int val = va_arg( *args , int );
240                len = 1;
241                buf[0] = val;
242                pbuf = &buf[0];
243                break;
244            }
245            case ('d'):             /* 32 bits decimal signed  */
246            {
247                int val = va_arg( *args , int );
248                if (val < 0) 
249                {
250                    val = -val;
251                    dev_txt_sync_write( "-" , 1 );
252                }
253                for(i = 0; i < 10; i++) 
254                {
255                    buf[9 - i] = HexaTab[val % 10];
256                    if (!(val /= 10)) break;
257                }
258                len =  i + 1;
259                pbuf = &buf[9 - i];
260                break;
261            }
262            case ('u'):             /* 32 bits decimal unsigned  */
263            {
264                uint32_t val = va_arg( *args , uint32_t );
265                for(i = 0; i < 10; i++) 
266                {
267                    buf[9 - i] = HexaTab[val % 10];
268                    if (!(val /= 10)) break;
269                }
270                len =  i + 1;
271                pbuf = &buf[9 - i];
272                break;
273            }
274            case ('x'):             /* 32 bits hexadecimal unsigned */
275            {
276                uint32_t val = va_arg( *args , uint32_t );
277                dev_txt_sync_write( "0x" , 2 );
278                for(i = 0; i < 8; i++) 
279                {
280                    buf[7 - i] = HexaTab[val & 0xF];
281                    if (!(val = (val>>4)))  break;
282                }
283                len =  i + 1;
284                pbuf = &buf[7 - i];
285                break;
286            }
287            case ('X'):             /* 32 bits hexadecimal unsigned  on 10 char */
288            {
289                uint32_t val = va_arg( *args , uint32_t );
290                dev_txt_sync_write( "0x" , 2 );
291                for(i = 0; i < 8; i++) 
292                {
293                    buf[7 - i] = HexaTab[val & 0xF];
294                    val = (val>>4);
295                }
296                len =  8;
297                pbuf = buf;
298                break;
299            }
300            case ('l'):            /* 64 bits hexadecimal unsigned */
301            {
302                unsigned long long val = va_arg( *args , unsigned long long );
303                dev_txt_sync_write( "0x" , 2 );
304                for(i = 0; i < 16; i++) 
305                {
306                    buf[15 - i] = HexaTab[val & 0xF];
307                    if (!(val = (val>>4)))  break;
308                }
309                len =  i + 1;
310                pbuf = &buf[15 - i];
311                break;
312            }
313            case ('L'):           /* 64 bits hexadecimal unsigned on 18 char */ 
314            {
315                unsigned long long val = va_arg( *args , unsigned long long );
316                dev_txt_sync_write( "0x" , 2 );
317                for(i = 0; i < 16; i++) 
318                {
319                    buf[15 - i] = HexaTab[val & 0xF];
320                    val = (val>>4);
321                }
322                len =  16;
323                pbuf = buf;
324                break;
325            }
326            case ('s'):             /* string */
327            {
328                char* str = va_arg( *args , char* );
329                while (str[len]) 
330                {
331                    len++;
332                }
333                pbuf = str;
334                break;
335            }
336            default:
337            {
338                dev_txt_sync_write( "\n[PANIC] in kernel_printf() : illegal format\n", 45 );
339            }
340        }
341
342        if( pbuf != NULL ) dev_txt_sync_write( pbuf, len );
343       
344        goto printf_text;
345    }
346
347}  // end kernel_printf()
348
349//////////////////////////////////
350void printk( char * format , ... )
351{
352    va_list       args;
353    reg_t         save_sr;
354
355    // get pointers on TXT0 chdev
356    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
357    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
358    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
359
360    // get extended pointer on remote TXT0 chdev lock
361    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
362
363    // get TXT0 lock in busy waiting mode
364    remote_spinlock_lock_busy( lock_xp , &save_sr );
365
366    // call kernel_printf on TXT0, in busy waiting mode
367    va_start( args , format );
368    kernel_printf( format , &args );
369    va_end( args );
370
371    // release lock
372    remote_spinlock_unlock_busy( lock_xp , save_sr );
373}
374
375/////////////////////////////////////////
376void nolock_printk( char * format , ... )
377{
378    va_list       args;
379
380    // call kernel_printf on TXT0, in busy waiting mode
381    va_start( args , format );
382    kernel_printf( format , &args );
383    va_end( args );
384}
385
386////////////////////////////////////
387void assert( bool_t       condition,
388             const char * function_name,
389             char       * format, ... )
390{
391    va_list       args;
392    uint32_t      save_sr;
393
394    if( condition == false )
395    {
396        // get pointers on TXT0 chdev
397        xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
398        cxy_t     txt0_cxy = GET_CXY( txt0_xp );
399        chdev_t * txt0_ptr = GET_PTR( txt0_xp );
400
401        // get extended pointer on remote TXT0 chdev lock
402        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
403
404        // get TXT0 lock in busy waiting mode
405        remote_spinlock_lock_busy( lock_xp , &save_sr );
406
407        // call nolock_printk to print function_name
408        nolock_printk("\n[PANIC] in %s : " , function_name );
409
410        // call kernel_printf on TXT0, in busy waiting to print format
411        va_start( args , format );
412        kernel_printf( format , &args );
413        va_end( args );
414
415        // release TXT0 lock
416        remote_spinlock_unlock_busy( lock_xp , save_sr );
417
418        // suicide
419        sys_exit( EXIT_FAILURE );
420    }
421}
422
423//////////////////////////
424void puts( char * string ) 
425{
426    uint32_t   save_sr;
427    uint32_t   n = 0;
428
429    // compute string length
430    while ( string[n] > 0 ) n++;
431
432    // get pointers on TXT0 chdev
433    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
434    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
435    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
436
437    // get extended pointer on remote TXT0 chdev lock
438    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
439
440    // get TXT0 lock in busy waiting mode
441    remote_spinlock_lock_busy( lock_xp , &save_sr );
442
443    // display string on TTY0
444    dev_txt_sync_write( string , n );
445
446    // release TXT0 lock in busy waiting mode
447    remote_spinlock_unlock_busy( lock_xp , save_sr );
448}
449
450
451/////////////////////////
452void putx( uint32_t val )
453{
454    static const char HexaTab[] = "0123456789ABCDEF";
455
456    char      buf[10];
457    uint32_t  c;
458    uint32_t  save_sr;
459
460    buf[0] = '0';
461    buf[1] = 'x';
462
463    // build buffer
464    for (c = 0; c < 8; c++) 
465    { 
466        buf[9 - c] = HexaTab[val & 0xF];
467        val = val >> 4;
468    }
469
470    // get pointers on TXT0 chdev
471    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
472    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
473    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
474
475    // get extended pointer on remote TXT0 chdev lock
476    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
477
478    // get TXT0 lock in busy waiting mode
479    remote_spinlock_lock_busy( lock_xp , &save_sr );
480
481    // display string on TTY0
482    dev_txt_sync_write( buf , 10 );
483
484    // release TXT0 lock in busy waiting mode
485    remote_spinlock_unlock_busy( lock_xp , save_sr );
486}
487
488/////////////////////////
489void putl( uint64_t val )
490{
491    static const char HexaTab[] = "0123456789ABCDEF";
492
493    char      buf[18];
494    uint32_t  c;
495    uint32_t  save_sr;
496
497    buf[0] = '0';
498    buf[1] = 'x';
499
500    // build buffer
501    for (c = 0; c < 16; c++) 
502    { 
503        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
504        val = val >> 4;
505    }
506
507    // get pointers on TXT0 chdev
508    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
509    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
510    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
511
512    // get extended pointer on remote TXT0 chdev lock
513    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
514
515    // get TXT0 lock in busy waiting mode
516    remote_spinlock_lock_busy( lock_xp , &save_sr );
517
518    // display string on TTY0
519    dev_txt_sync_write( buf , 18 );
520
521    // release TXT0 lock in busy waiting mode
522    remote_spinlock_unlock_busy( lock_xp , save_sr );
523}
524
525
526// Local Variables:
527// tab-width: 4
528// c-basic-offset: 4
529// c-file-offsets:((innamespace . 0)(inline-open . 0))
530// indent-tabs-mode: nil
531// End:
532// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
533
Note: See TracBrowser for help on using the repository browser.