Commit | Line | Data |
---|---|---|
247b365d WAF |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | //! Printing facilities. | |
4 | //! | |
5 | //! C header: [`include/linux/printk.h`](../../../../include/linux/printk.h) | |
6 | //! | |
7 | //! Reference: <https://www.kernel.org/doc/html/latest/core-api/printk-basics.html> | |
8 | ||
9 | use core::{ | |
10 | ffi::{c_char, c_void}, | |
11 | fmt, | |
12 | }; | |
13 | ||
14 | use crate::str::RawFormatter; | |
15 | ||
16 | #[cfg(CONFIG_PRINTK)] | |
17 | use crate::bindings; | |
18 | ||
19 | // Called from `vsprintf` with format specifier `%pA`. | |
20 | #[no_mangle] | |
c682e4c3 DG |
21 | unsafe extern "C" fn rust_fmt_argument( |
22 | buf: *mut c_char, | |
23 | end: *mut c_char, | |
24 | ptr: *const c_void, | |
25 | ) -> *mut c_char { | |
247b365d WAF |
26 | use fmt::Write; |
27 | // SAFETY: The C contract guarantees that `buf` is valid if it's less than `end`. | |
28 | let mut w = unsafe { RawFormatter::from_ptrs(buf.cast(), end.cast()) }; | |
29 | let _ = w.write_fmt(unsafe { *(ptr as *const fmt::Arguments<'_>) }); | |
30 | w.pos().cast() | |
31 | } | |
32 | ||
33 | /// Format strings. | |
34 | /// | |
35 | /// Public but hidden since it should only be used from public macros. | |
36 | #[doc(hidden)] | |
37 | pub mod format_strings { | |
38 | use crate::bindings; | |
39 | ||
40 | /// The length we copy from the `KERN_*` kernel prefixes. | |
41 | const LENGTH_PREFIX: usize = 2; | |
42 | ||
43 | /// The length of the fixed format strings. | |
44 | pub const LENGTH: usize = 10; | |
45 | ||
46 | /// Generates a fixed format string for the kernel's [`_printk`]. | |
47 | /// | |
48 | /// The format string is always the same for a given level, i.e. for a | |
49 | /// given `prefix`, which are the kernel's `KERN_*` constants. | |
50 | /// | |
51 | /// [`_printk`]: ../../../../include/linux/printk.h | |
52 | const fn generate(is_cont: bool, prefix: &[u8; 3]) -> [u8; LENGTH] { | |
53 | // Ensure the `KERN_*` macros are what we expect. | |
54 | assert!(prefix[0] == b'\x01'); | |
55 | if is_cont { | |
56 | assert!(prefix[1] == b'c'); | |
57 | } else { | |
58 | assert!(prefix[1] >= b'0' && prefix[1] <= b'7'); | |
59 | } | |
60 | assert!(prefix[2] == b'\x00'); | |
61 | ||
62 | let suffix: &[u8; LENGTH - LENGTH_PREFIX] = if is_cont { | |
63 | b"%pA\0\0\0\0\0" | |
64 | } else { | |
65 | b"%s: %pA\0" | |
66 | }; | |
67 | ||
68 | [ | |
69 | prefix[0], prefix[1], suffix[0], suffix[1], suffix[2], suffix[3], suffix[4], suffix[5], | |
70 | suffix[6], suffix[7], | |
71 | ] | |
72 | } | |
73 | ||
74 | // Generate the format strings at compile-time. | |
75 | // | |
76 | // This avoids the compiler generating the contents on the fly in the stack. | |
77 | // | |
78 | // Furthermore, `static` instead of `const` is used to share the strings | |
79 | // for all the kernel. | |
80 | pub static EMERG: [u8; LENGTH] = generate(false, bindings::KERN_EMERG); | |
4c7f9499 MO |
81 | pub static ALERT: [u8; LENGTH] = generate(false, bindings::KERN_ALERT); |
82 | pub static CRIT: [u8; LENGTH] = generate(false, bindings::KERN_CRIT); | |
83 | pub static ERR: [u8; LENGTH] = generate(false, bindings::KERN_ERR); | |
84 | pub static WARNING: [u8; LENGTH] = generate(false, bindings::KERN_WARNING); | |
85 | pub static NOTICE: [u8; LENGTH] = generate(false, bindings::KERN_NOTICE); | |
247b365d | 86 | pub static INFO: [u8; LENGTH] = generate(false, bindings::KERN_INFO); |
4c7f9499 | 87 | pub static DEBUG: [u8; LENGTH] = generate(false, bindings::KERN_DEBUG); |
fc6c7cac | 88 | pub static CONT: [u8; LENGTH] = generate(true, bindings::KERN_CONT); |
247b365d WAF |
89 | } |
90 | ||
91 | /// Prints a message via the kernel's [`_printk`]. | |
92 | /// | |
93 | /// Public but hidden since it should only be used from public macros. | |
94 | /// | |
95 | /// # Safety | |
96 | /// | |
97 | /// The format string must be one of the ones in [`format_strings`], and | |
98 | /// the module name must be null-terminated. | |
99 | /// | |
100 | /// [`_printk`]: ../../../../include/linux/_printk.h | |
101 | #[doc(hidden)] | |
102 | #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))] | |
103 | pub unsafe fn call_printk( | |
104 | format_string: &[u8; format_strings::LENGTH], | |
105 | module_name: &[u8], | |
106 | args: fmt::Arguments<'_>, | |
107 | ) { | |
108 | // `_printk` does not seem to fail in any path. | |
109 | #[cfg(CONFIG_PRINTK)] | |
110 | unsafe { | |
111 | bindings::_printk( | |
112 | format_string.as_ptr() as _, | |
113 | module_name.as_ptr(), | |
114 | &args as *const _ as *const c_void, | |
115 | ); | |
116 | } | |
117 | } | |
118 | ||
fc6c7cac MO |
119 | /// Prints a message via the kernel's [`_printk`] for the `CONT` level. |
120 | /// | |
121 | /// Public but hidden since it should only be used from public macros. | |
122 | /// | |
123 | /// [`_printk`]: ../../../../include/linux/printk.h | |
124 | #[doc(hidden)] | |
125 | #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))] | |
126 | pub fn call_printk_cont(args: fmt::Arguments<'_>) { | |
127 | // `_printk` does not seem to fail in any path. | |
128 | // | |
129 | // SAFETY: The format string is fixed. | |
130 | #[cfg(CONFIG_PRINTK)] | |
131 | unsafe { | |
132 | bindings::_printk( | |
133 | format_strings::CONT.as_ptr() as _, | |
134 | &args as *const _ as *const c_void, | |
135 | ); | |
136 | } | |
137 | } | |
138 | ||
247b365d WAF |
139 | /// Performs formatting and forwards the string to [`call_printk`]. |
140 | /// | |
141 | /// Public but hidden since it should only be used from public macros. | |
142 | #[doc(hidden)] | |
143 | #[cfg(not(testlib))] | |
144 | #[macro_export] | |
145 | #[allow(clippy::crate_in_macro_def)] | |
146 | macro_rules! print_macro ( | |
147 | // The non-continuation cases (most of them, e.g. `INFO`). | |
fc6c7cac | 148 | ($format_string:path, false, $($arg:tt)+) => ( |
6618d69a MO |
149 | // To remain sound, `arg`s must be expanded outside the `unsafe` block. |
150 | // Typically one would use a `let` binding for that; however, `format_args!` | |
151 | // takes borrows on the arguments, but does not extend the scope of temporaries. | |
152 | // Therefore, a `match` expression is used to keep them around, since | |
153 | // the scrutinee is kept until the end of the `match`. | |
154 | match format_args!($($arg)+) { | |
155 | // SAFETY: This hidden macro should only be called by the documented | |
156 | // printing macros which ensure the format string is one of the fixed | |
157 | // ones. All `__LOG_PREFIX`s are null-terminated as they are generated | |
158 | // by the `module!` proc macro or fixed values defined in a kernel | |
159 | // crate. | |
160 | args => unsafe { | |
161 | $crate::print::call_printk( | |
162 | &$format_string, | |
163 | crate::__LOG_PREFIX, | |
164 | args, | |
165 | ); | |
166 | } | |
247b365d WAF |
167 | } |
168 | ); | |
fc6c7cac MO |
169 | |
170 | // The `CONT` case. | |
171 | ($format_string:path, true, $($arg:tt)+) => ( | |
172 | $crate::print::call_printk_cont( | |
173 | format_args!($($arg)+), | |
174 | ); | |
175 | ); | |
247b365d WAF |
176 | ); |
177 | ||
178 | /// Stub for doctests | |
179 | #[cfg(testlib)] | |
180 | #[macro_export] | |
181 | macro_rules! print_macro ( | |
182 | ($format_string:path, $e:expr, $($arg:tt)+) => ( | |
183 | () | |
184 | ); | |
185 | ); | |
186 | ||
187 | // We could use a macro to generate these macros. However, doing so ends | |
188 | // up being a bit ugly: it requires the dollar token trick to escape `$` as | |
189 | // well as playing with the `doc` attribute. Furthermore, they cannot be easily | |
190 | // imported in the prelude due to [1]. So, for the moment, we just write them | |
191 | // manually, like in the C side; while keeping most of the logic in another | |
192 | // macro, i.e. [`print_macro`]. | |
193 | // | |
194 | // [1]: https://github.com/rust-lang/rust/issues/52234 | |
195 | ||
196 | /// Prints an emergency-level message (level 0). | |
197 | /// | |
198 | /// Use this level if the system is unusable. | |
199 | /// | |
200 | /// Equivalent to the kernel's [`pr_emerg`] macro. | |
201 | /// | |
202 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
203 | /// `alloc::format!` for information about the formatting syntax. | |
204 | /// | |
205 | /// [`pr_emerg`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_emerg | |
206 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
207 | /// | |
208 | /// # Examples | |
209 | /// | |
210 | /// ``` | |
211 | /// pr_emerg!("hello {}\n", "there"); | |
212 | /// ``` | |
213 | #[macro_export] | |
214 | macro_rules! pr_emerg ( | |
215 | ($($arg:tt)*) => ( | |
fc6c7cac | 216 | $crate::print_macro!($crate::print::format_strings::EMERG, false, $($arg)*) |
247b365d WAF |
217 | ) |
218 | ); | |
219 | ||
4c7f9499 MO |
220 | /// Prints an alert-level message (level 1). |
221 | /// | |
222 | /// Use this level if action must be taken immediately. | |
223 | /// | |
224 | /// Equivalent to the kernel's [`pr_alert`] macro. | |
225 | /// | |
226 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
227 | /// `alloc::format!` for information about the formatting syntax. | |
228 | /// | |
229 | /// [`pr_alert`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_alert | |
230 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
231 | /// | |
232 | /// # Examples | |
233 | /// | |
234 | /// ``` | |
235 | /// pr_alert!("hello {}\n", "there"); | |
236 | /// ``` | |
237 | #[macro_export] | |
238 | macro_rules! pr_alert ( | |
239 | ($($arg:tt)*) => ( | |
fc6c7cac | 240 | $crate::print_macro!($crate::print::format_strings::ALERT, false, $($arg)*) |
4c7f9499 MO |
241 | ) |
242 | ); | |
243 | ||
244 | /// Prints a critical-level message (level 2). | |
245 | /// | |
246 | /// Use this level for critical conditions. | |
247 | /// | |
248 | /// Equivalent to the kernel's [`pr_crit`] macro. | |
249 | /// | |
250 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
251 | /// `alloc::format!` for information about the formatting syntax. | |
252 | /// | |
253 | /// [`pr_crit`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_crit | |
254 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
255 | /// | |
256 | /// # Examples | |
257 | /// | |
258 | /// ``` | |
259 | /// pr_crit!("hello {}\n", "there"); | |
260 | /// ``` | |
261 | #[macro_export] | |
262 | macro_rules! pr_crit ( | |
263 | ($($arg:tt)*) => ( | |
fc6c7cac | 264 | $crate::print_macro!($crate::print::format_strings::CRIT, false, $($arg)*) |
4c7f9499 MO |
265 | ) |
266 | ); | |
267 | ||
268 | /// Prints an error-level message (level 3). | |
269 | /// | |
270 | /// Use this level for error conditions. | |
271 | /// | |
272 | /// Equivalent to the kernel's [`pr_err`] macro. | |
273 | /// | |
274 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
275 | /// `alloc::format!` for information about the formatting syntax. | |
276 | /// | |
277 | /// [`pr_err`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_err | |
278 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
279 | /// | |
280 | /// # Examples | |
281 | /// | |
282 | /// ``` | |
283 | /// pr_err!("hello {}\n", "there"); | |
284 | /// ``` | |
285 | #[macro_export] | |
286 | macro_rules! pr_err ( | |
287 | ($($arg:tt)*) => ( | |
fc6c7cac | 288 | $crate::print_macro!($crate::print::format_strings::ERR, false, $($arg)*) |
4c7f9499 MO |
289 | ) |
290 | ); | |
291 | ||
292 | /// Prints a warning-level message (level 4). | |
293 | /// | |
294 | /// Use this level for warning conditions. | |
295 | /// | |
296 | /// Equivalent to the kernel's [`pr_warn`] macro. | |
297 | /// | |
298 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
299 | /// `alloc::format!` for information about the formatting syntax. | |
300 | /// | |
301 | /// [`pr_warn`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_warn | |
302 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
303 | /// | |
304 | /// # Examples | |
305 | /// | |
306 | /// ``` | |
307 | /// pr_warn!("hello {}\n", "there"); | |
308 | /// ``` | |
309 | #[macro_export] | |
310 | macro_rules! pr_warn ( | |
311 | ($($arg:tt)*) => ( | |
fc6c7cac | 312 | $crate::print_macro!($crate::print::format_strings::WARNING, false, $($arg)*) |
4c7f9499 MO |
313 | ) |
314 | ); | |
315 | ||
316 | /// Prints a notice-level message (level 5). | |
317 | /// | |
318 | /// Use this level for normal but significant conditions. | |
319 | /// | |
320 | /// Equivalent to the kernel's [`pr_notice`] macro. | |
321 | /// | |
322 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
323 | /// `alloc::format!` for information about the formatting syntax. | |
324 | /// | |
325 | /// [`pr_notice`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_notice | |
326 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
327 | /// | |
328 | /// # Examples | |
329 | /// | |
330 | /// ``` | |
331 | /// pr_notice!("hello {}\n", "there"); | |
332 | /// ``` | |
333 | #[macro_export] | |
334 | macro_rules! pr_notice ( | |
335 | ($($arg:tt)*) => ( | |
fc6c7cac | 336 | $crate::print_macro!($crate::print::format_strings::NOTICE, false, $($arg)*) |
4c7f9499 MO |
337 | ) |
338 | ); | |
339 | ||
247b365d WAF |
340 | /// Prints an info-level message (level 6). |
341 | /// | |
342 | /// Use this level for informational messages. | |
343 | /// | |
344 | /// Equivalent to the kernel's [`pr_info`] macro. | |
345 | /// | |
346 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
347 | /// `alloc::format!` for information about the formatting syntax. | |
348 | /// | |
349 | /// [`pr_info`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_info | |
350 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
351 | /// | |
352 | /// # Examples | |
353 | /// | |
354 | /// ``` | |
355 | /// pr_info!("hello {}\n", "there"); | |
356 | /// ``` | |
357 | #[macro_export] | |
358 | #[doc(alias = "print")] | |
359 | macro_rules! pr_info ( | |
360 | ($($arg:tt)*) => ( | |
fc6c7cac | 361 | $crate::print_macro!($crate::print::format_strings::INFO, false, $($arg)*) |
247b365d WAF |
362 | ) |
363 | ); | |
4c7f9499 MO |
364 | |
365 | /// Prints a debug-level message (level 7). | |
366 | /// | |
367 | /// Use this level for debug messages. | |
368 | /// | |
369 | /// Equivalent to the kernel's [`pr_debug`] macro, except that it doesn't support dynamic debug | |
370 | /// yet. | |
371 | /// | |
372 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
373 | /// `alloc::format!` for information about the formatting syntax. | |
374 | /// | |
375 | /// [`pr_debug`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_debug | |
376 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
377 | /// | |
378 | /// # Examples | |
379 | /// | |
380 | /// ``` | |
381 | /// pr_debug!("hello {}\n", "there"); | |
382 | /// ``` | |
383 | #[macro_export] | |
384 | #[doc(alias = "print")] | |
385 | macro_rules! pr_debug ( | |
386 | ($($arg:tt)*) => ( | |
387 | if cfg!(debug_assertions) { | |
fc6c7cac | 388 | $crate::print_macro!($crate::print::format_strings::DEBUG, false, $($arg)*) |
4c7f9499 MO |
389 | } |
390 | ) | |
391 | ); | |
fc6c7cac MO |
392 | |
393 | /// Continues a previous log message in the same line. | |
394 | /// | |
395 | /// Use only when continuing a previous `pr_*!` macro (e.g. [`pr_info!`]). | |
396 | /// | |
397 | /// Equivalent to the kernel's [`pr_cont`] macro. | |
398 | /// | |
399 | /// Mimics the interface of [`std::print!`]. See [`core::fmt`] and | |
400 | /// `alloc::format!` for information about the formatting syntax. | |
401 | /// | |
402 | /// [`pr_cont`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html#c.pr_cont | |
403 | /// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html | |
404 | /// | |
405 | /// # Examples | |
406 | /// | |
407 | /// ``` | |
408 | /// # use kernel::pr_cont; | |
409 | /// pr_info!("hello"); | |
410 | /// pr_cont!(" {}\n", "there"); | |
411 | /// ``` | |
412 | #[macro_export] | |
413 | macro_rules! pr_cont ( | |
414 | ($($arg:tt)*) => ( | |
415 | $crate::print_macro!($crate::print::format_strings::CONT, true, $($arg)*) | |
416 | ) | |
417 | ); |