AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
printk.c
Go to the documentation of this file.
1
13
14#include <core/system.h>
15#include <ds/queue.h>
16#include <sys/waitq.h>
17
18#include <core/string.h>
19#include <console/earlycon.h>
20#include <ds/ringbuf.h>
21
22/* The kernel's message buffer, and the readers of /dev/kmsg waiting for
23 * messages. */
24#define KMSG_SIZE 8192
26struct waitq *kmsg_wait = &(struct waitq){0};
27
28static int use_earlycon = 1;
29
35{
36 use_earlycon = 0;
37}
38
39static void (*console_write)(const char *s, size_t len);
40
47void printk_console(void (*write)(const char *s, size_t len))
48{
49 console_write = write;
50}
51
54static int putc(char c)
55{
56 ringbuf_write_overwrite(kmsg, 1, &c);
57
58 if (console_write)
59 console_write(&c, 1);
60
61 if (use_earlycon)
62 return earlycon_putc(c);
63 return 0;
64}
65
67static int puts(char *s)
68{
69 s = s? s : "(null)";
70
71 int len = strlen(s);
72 ringbuf_write_overwrite(kmsg, len, s);
73
74 if (console_write)
75 console_write(s, len);
76
77 if (use_earlycon)
78 return earlycon_puts(s);
79
80 return 0;
81}
82
84static int putx(uint32_t val)
85{
86 if (!val)
87 return puts("0");
88
89 char *enc = "0123456789ABCDEF";
90 char buf[9];
91 buf[8] = '\0';
92 uint8_t i = 8;
93
94 while (val && i) {
95 buf[--i] = enc[val & 0xF];
96 val >>= 4;
97 }
98
99 return puts(&buf[i]);
100}
101
103static int putlx(uint64_t val)
104{
105 char *enc = "0123456789ABCDEF";
106 char buf[17];
107 buf[16] = '\0';
108 uint8_t i = 16;
109 while (i) {
110 buf[--i] = enc[val&0xF];
111 val >>= 4;
112 }
113 return puts(buf);
114}
115
117static int putud(uint32_t val)
118{
119 char buf[11];
120 buf[10] = '\0';
121 if (!val) { buf[9] = '0'; return puts(&buf[9]); }
122 uint8_t i = 10;
123 while (val) {
124 buf[--i] = val%10 + '0';
125 val = (val-val%10)/10;
126 }
127 return puts(buf+i);
128}
129
131static int putul(uint64_t val)
132{
133 char buf[21];
134 buf[20] = '\0';
135 if (!val) { buf[19] = '0'; return puts(&buf[19]); }
136 uint8_t i = 20;
137 while (val) {
138 buf[--i] = val%10 + '0';
139 val = (val-val%10)/10;
140 }
141 return puts(buf+i);
142}
143
145static int putb(uint8_t val)
146{
147 char buf[9];
148 buf[8] = '\0';
149 uint8_t i = 8;
150 while (i) {
151 buf[--i] = '0' + (val & 1);
152 val >>= 1;
153 }
154 return puts(buf);
155}
156
164int vprintk(const char *fmt, va_list args)
165{
166 int ret = 0;
167 while (*fmt)
168 switch (*fmt) {
169 case '%':
170 ++fmt;
171 switch (*fmt) {
172 case 'c': /* a character */
173 ret += putc((char)va_arg(args, int));
174 break;
175 case 's': /* a string */
176 ret += puts((char*)va_arg(args, char*));
177 break;
178 case 'd': /* a signed decimal */
179 {
180 int32_t val = va_arg(args, int32_t);
181 if (val < 0) {
182 ret += putc('-');
183 ret += putud(-(uint32_t) val);
184 } else {
185 ret += putud((uint32_t) val);
186 }
187 }
188 break;
189 case 'u': /* an unsigned decimal */
190 ret += putud((uint32_t)va_arg(args, uint32_t));
191 break;
192 case 'l': /* a 64-bit number */
193 switch (*++fmt) {
194 case 'x': /* in hexadecimal */
195 ret += putlx((uint64_t)va_arg(args, uint64_t));
196 break;
197 case 'd': /* a signed decimal */
198 {
199 int64_t val = va_arg(args, int64_t);
200 if (val < 0) {
201 ret += putc('-');
202 ret += putul(-(uint64_t) val);
203 } else {
204 ret += putul((uint64_t) val);
205 }
206 }
207 break;
208 case 'u': /* an unsigned decimal */
209 ret += putul((uint64_t)va_arg(args, uint64_t));
210 break;
211 default:
212 ret += putc(*--fmt);
213 }
214 break;
215
216 case 'b': /* a byte in binary */
217 ret += putb((uint8_t)(uint32_t)va_arg(args, uint32_t));
218 break;
219 case 'x': /* hexadecimal */
220 ret += putx((uint32_t)va_arg(args, uint32_t));
221 break;
222 case 'p': /* a pointer */
223 ret += puts("0x");
224#if ARCH_BITS==32
225 ret += putx((uint32_t)va_arg(args, uint32_t));
226#elif ARCH_BITS==64
227 ret += putlx((uint64_t)va_arg(args, uint64_t));
228#endif
229 break;
230 default:
231 ret += putc(*(--fmt));
232 }
233 ++fmt;
234 break;
235 default:
236 ret += putc(*fmt);
237 ++fmt;
238 }
239
240 return ret;
241}
242
249int printk(const char *fmt, ...)
250{
251 va_list args;
252 va_start(args, fmt);
253 int ret = vprintk(fmt, args);
254 va_end(args);
255
256 return ret;
257}
int earlycon_putc(char c)
Writes a character on the early console.
Definition earlycon.c:23
int earlycon_puts(char *s)
Writes a string on the early console.
Definition earlycon.c:38
#define KMSG_SIZE
Definition printk.c:24
static int use_earlycon
Definition printk.c:28
static int putc(char c)
Writes one character of a message.
Definition printk.c:54
void earlycon_disable()
Stops sending the kernel's messages to the early console, once a real console has taken over.
Definition printk.c:34
static int putx(uint32_t val)
Writes a 32-bit number in hexadecimal, without leading zeros.
Definition printk.c:84
static int putlx(uint64_t val)
Writes a 64-bit number in hexadecimal, all 16 digits.
Definition printk.c:103
struct waitq * kmsg_wait
Definition printk.c:26
void printk_console(void(*write)(const char *s, size_t len))
Registers the console that the kernel's messages are written to, besides the message buffer.
Definition printk.c:47
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
static void(*) console_write(const char *s, size_t len)
Definition printk.c:39
struct ringbuf * kmsg
Definition printk.c:25
static int puts(char *s)
Writes a string of a message ("(null)" for NULL).
Definition printk.c:67
int vprintk(const char *fmt, va_list args)
Writes a kernel message, with its arguments in a va_list.
Definition printk.c:164
static int putud(uint32_t val)
Writes an unsigned 32-bit number in decimal.
Definition printk.c:117
static int putul(uint64_t val)
Writes an unsigned 64-bit number in decimal.
Definition printk.c:131
static int putb(uint8_t val)
Writes a byte in binary, all 8 digits.
Definition printk.c:145
#define RINGBUF_NEW(sz)
Definition ringbuf.h:26
#define va_list
Definition stdarg.h:6
#define va_end(v)
Definition stdarg.h:8
#define va_arg(v, l)
Definition stdarg.h:9
#define va_start(v, l)
Definition stdarg.h:7
unsigned int uint32_t
Definition stddef.h:22
signed long long int int64_t
Definition stddef.h:19
signed int int32_t
Definition stddef.h:18
unsigned char uint8_t
Definition stddef.h:20
unsigned long long int uint64_t
Definition stddef.h:23
A ring buffer.
Definition ringbuf.h:18
Definition waitq.h:19