1 /*
2  * Copyright 2014, General Dynamics C4 Systems
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #pragma once
8 
9 #include <config.h>
10 
11 #ifdef CONFIG_DEBUG_BUILD
12 /* io for dumping capdl */
13 unsigned char kernel_getDebugChar(void);
14 #endif
15 
16 
17 #ifdef CONFIG_PRINTING
18 
19 #include <arch/types.h>
20 #include <stdarg.h>
21 
22 /* the actual output function */
23 void kernel_putDebugChar(unsigned char c);
24 
25 /* This is the actual implementation of the kernel printing API. It must never
26  * be called directly from anywhere except the function defined in this file.
27  */
28 int impl_kvprintf(const char *format, va_list ap);
29 int impl_ksnvprintf(char *str, word_t size, const char *format, va_list ap);
30 
31 /*
32  *------------------------------------------------------------------------------
33  * Kernel printing API
34  *------------------------------------------------------------------------------
35  */
36 
37 /* Writes a character to the kernel output channel. This is used to implement
38  * the syscall SysDebugPutChar.
39  */
kernel_putchar(char c)40 static inline void kernel_putchar(
41     char c)
42 {
43     /* Write to target specific debug output channel. */
44     kernel_putDebugChar(c);
45 }
46 
47 /* Writes a character to the active output channel. This is used by all code
48  * related to printf(). Contrary to the common signature of putchar(), there is
49  * no return value here.
50  */
putchar(char c)51 static inline void putchar(
52     char c)
53 {
54     /* Write to target specific debug output channel. Purposely, we do not call
55      * kernel_putchar() here, as the kernel printf() channel is semantically
56      * different from the syscall SysDebugPutChar channel. The unification
57      * of both channels happens at the lower layer eventually
58      */
59     kernel_putDebugChar(c);
60 }
61 
62 /* Writes the string and a trailing newline. There is no point to enforce a
63  * kernel_puts(), as this is just a wrapper for putchar() anyway.
64  */
puts(const char * str)65 static inline int puts(
66     const char *str)
67 {
68     if (str) {
69         while (*str) {
70             putchar(*str++);
71         }
72     }
73     putchar('\n');
74     /* Standards define that a non-negative number is returned on success. */
75     return 0;
76 }
77 
78 /* There should only be a kprintf() that all kernel code must use for printing,
79  * but for convenience we provide a printf() here.
80  */
printf(const char * format,...)81 static inline __attribute__((format(printf, 1, 2))) int printf(
82     const char *format,
83     ...)
84 {
85     va_list args;
86     va_start(args, format);
87     int ret = impl_kvprintf(format, args); /* will call putchar() eventually */
88     va_end(args);
89     return ret;
90 }
91 
92 /* Provide the standard snprintf() for write formatted data into a buffer, which
93  * can then be printed or stored.
94  */
snprintf(char * buf,word_t size,const char * format,...)95 static inline __attribute__((format(printf, 3, 4))) int snprintf(
96     char *buf,
97     word_t size,
98     const char *format,
99     ...)
100 {
101     va_list args;
102     va_start(args, format);
103     int ret = impl_ksnvprintf(buf, size, format, args);
104     va_end(args);
105     return ret;
106 }
107 
108 #else /* not CONFIG_PRINTING */
109 
110 /* The verification runs on the output of the preprocessing stage of a release
111  * build configuration, CONFIG_PRINTING is not enabled there. We remove all
112  * calls to printf() completely from the code base, because neither printf() nor
113  * the usage of a variable argument list is supported by the verification
114  * toolchain. It would just reject the code if it encounters any unsupported
115  * things.
116  */
117 #define printf(...)             ((void)(0))
118 
119 /* Seems there is no need to define out these functions, they are use by code
120  * that is active with CONFIG_PRINTING only.
121  *
122  *   #define kernel_putchar(...)     ((void)(0))
123  *   #define putchar(...)            ((void)(0))
124  *   #define puts(...)               ((void)(0))
125  *   #define snprintf(...)           ((void)(0))
126  */
127 
128 #endif /* [not] CONFIG_PRINTING */
129