blob: 99710e60be9275ba295815db0beb1892b6232034 [file] [log] [blame]
Angel Ponsb706ab32020-04-02 23:48:09 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Angel Ponsb706ab32020-04-02 23:48:09 +02002
Eric Biederman8ca8d762003-04-22 19:02:15 +00003/*
Damien Roth4e7e9872016-01-16 18:59:51 -07004 * blatantly copied from linux/kernel/printk.c
Eric Biederman8ca8d762003-04-22 19:02:15 +00005 */
Eric Biederman8ca8d762003-04-22 19:02:15 +00006
Kyösti Mälkkie613d702019-02-12 14:16:21 +02007#include <console/cbmem_console.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00008#include <console/console.h>
Kyösti Mälkki40760722014-02-27 19:30:18 +02009#include <console/streams.h>
Edward O'Callaghan0ddb8262014-06-17 18:37:08 +100010#include <console/vtxprintf.h>
11#include <smp/spinlock.h>
12#include <smp/node.h>
Kyösti Mälkki45ddb432019-11-02 14:12:18 +020013#include <timer.h>
Elyes Haouas94830012022-10-02 12:29:03 +020014#include <types.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000015
Myles Watson2e672732009-11-12 16:38:03 +000016DECLARE_SPIN_LOCK(console_lock)
Eric Biederman8ca8d762003-04-22 19:02:15 +000017
Kyösti Mälkki05fe16c2019-12-01 08:38:11 +020018#define TRACK_CONSOLE_TIME (!ENV_SMM && CONFIG(HAVE_MONOTONIC_TIMER))
Kyösti Mälkki45ddb432019-11-02 14:12:18 +020019
20static struct mono_time mt_start, mt_stop;
21static long console_usecs;
22
23static void console_time_run(void)
24{
Kyösti Mälkki05fe16c2019-12-01 08:38:11 +020025 if (TRACK_CONSOLE_TIME && boot_cpu())
Kyösti Mälkki45ddb432019-11-02 14:12:18 +020026 timer_monotonic_get(&mt_start);
27}
28
29static void console_time_stop(void)
30{
Kyösti Mälkki05fe16c2019-12-01 08:38:11 +020031 if (TRACK_CONSOLE_TIME && boot_cpu()) {
Kyösti Mälkki45ddb432019-11-02 14:12:18 +020032 timer_monotonic_get(&mt_stop);
33 console_usecs += mono_time_diff_microseconds(&mt_start, &mt_stop);
34 }
35}
36
37void console_time_report(void)
38{
39 if (!TRACK_CONSOLE_TIME)
40 return;
41
Kyösti Mälkki94694a82019-11-02 18:14:31 +020042 printk(BIOS_DEBUG, "BS: " ENV_STRING " times (exec / console): total (unknown) / %ld ms\n",
Kyösti Mälkki45ddb432019-11-02 14:12:18 +020043 DIV_ROUND_CLOSEST(console_usecs, USECS_PER_MSEC));
44}
45
46long console_time_get_and_reset(void)
47{
48 if (!TRACK_CONSOLE_TIME)
49 return 0;
50
51 long elapsed = console_usecs;
52 console_usecs = 0;
53 return elapsed;
54}
55
Kyösti Mälkki657e0be2014-02-04 19:03:57 +020056void do_putchar(unsigned char byte)
57{
Kyösti Mälkki45ddb432019-11-02 14:12:18 +020058 console_time_run();
Kyösti Mälkki657e0be2014-02-04 19:03:57 +020059 console_tx_byte(byte);
Kyösti Mälkki45ddb432019-11-02 14:12:18 +020060 console_time_stop();
Kyösti Mälkki657e0be2014-02-04 19:03:57 +020061}
62
Julius Wernerb6cf6422022-02-02 17:21:02 -080063union log_state {
64 void *as_ptr;
65 struct {
66 uint8_t level;
67 uint8_t speed;
68 };
69};
70
Mario Scheithauerf6056112022-02-22 09:46:33 +010071#define LOG_FAST(state) (HAS_ONLY_FAST_CONSOLES || ((state).speed == CONSOLE_LOG_FAST))
Julius Werner266041f2022-02-03 17:25:44 -080072
Julius Werner7cd8ba62022-01-21 15:15:29 -080073static void wrap_interactive_printf(const char *fmt, ...)
74{
75 va_list args;
76 va_start(args, fmt);
77 vtxprintf(console_interactive_tx_byte, fmt, args, NULL);
Julius Wernerababf012022-02-08 16:37:41 -080078 va_end(args);
Julius Werner7cd8ba62022-01-21 15:15:29 -080079}
80
81static void line_start(union log_state state)
82{
83 if (state.level > BIOS_LOG_PREFIX_MAX_LEVEL)
84 return;
Julius Werner984d03c2022-01-21 15:33:47 -080085
86 /* Stored consoles just get a single control char marker to save space. If we are in
87 LOG_FAST mode, just write the marker to CBMC and exit -- the rest of this function
88 implements the LOG_ALL case. */
89 unsigned char marker = BIOS_LOG_LEVEL_TO_MARKER(state.level);
Julius Werner266041f2022-02-03 17:25:44 -080090 if (LOG_FAST(state)) {
Julius Werner984d03c2022-01-21 15:33:47 -080091 __cbmemc_tx_byte(marker);
Julius Werner7cd8ba62022-01-21 15:15:29 -080092 return;
Julius Werner984d03c2022-01-21 15:33:47 -080093 }
94 console_stored_tx_byte(marker, NULL);
Julius Werner7cd8ba62022-01-21 15:15:29 -080095
Julius Wernera120e0d2022-01-21 15:24:12 -080096 /* Interactive consoles get a `[DEBUG] ` style readable prefix,
97 and potentially an escape sequence for highlighting. */
98 if (CONFIG(CONSOLE_USE_ANSI_ESCAPES))
99 wrap_interactive_printf(BIOS_LOG_ESCAPE_PATTERN, bios_log_escape[state.level]);
Igor Bagnuckif0d65212022-03-03 11:41:57 +0100100 if (CONFIG(CONSOLE_USE_LOGLEVEL_PREFIX))
101 wrap_interactive_printf(BIOS_LOG_PREFIX_PATTERN, bios_log_prefix[state.level]);
Julius Werner7cd8ba62022-01-21 15:15:29 -0800102}
103
Julius Wernera120e0d2022-01-21 15:24:12 -0800104static void line_end(union log_state state)
105{
Julius Werner266041f2022-02-03 17:25:44 -0800106 if (CONFIG(CONSOLE_USE_ANSI_ESCAPES) && !LOG_FAST(state))
Julius Wernera120e0d2022-01-21 15:24:12 -0800107 wrap_interactive_printf(BIOS_LOG_ESCAPE_RESET);
108}
109
Kyösti Mälkki77f43e92014-02-04 19:50:07 +0200110static void wrap_putchar(unsigned char byte, void *data)
Kyösti Mälkkib04e0ff2014-02-04 14:28:17 +0200111{
Julius Wernerb6cf6422022-02-02 17:21:02 -0800112 union log_state state = { .as_ptr = data };
Julius Werner7cd8ba62022-01-21 15:15:29 -0800113 static bool line_started = false;
114
115 if (byte == '\n') {
Julius Wernera120e0d2022-01-21 15:24:12 -0800116 line_end(state);
Julius Werner7cd8ba62022-01-21 15:15:29 -0800117 line_started = false;
118 } else if (!line_started) {
119 line_start(state);
120 line_started = true;
121 }
Kyösti Mälkkie613d702019-02-12 14:16:21 +0200122
Julius Werner266041f2022-02-03 17:25:44 -0800123 if (LOG_FAST(state))
Julius Wernerb6cf6422022-02-02 17:21:02 -0800124 __cbmemc_tx_byte(byte);
125 else
126 console_tx_byte(byte);
Kyösti Mälkkib04e0ff2014-02-04 14:28:17 +0200127}
128
Nico Huber7cc14ac2021-03-27 20:03:02 +0100129int vprintk(int msg_level, const char *fmt, va_list args)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000130{
Julius Wernerb6cf6422022-02-02 17:21:02 -0800131 union log_state state = { .level = msg_level };
132 int i;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000133
Kyösti Mälkki21160a72019-08-17 17:29:36 +0300134 if (CONFIG(SQUELCH_EARLY_SMP) && ENV_ROMSTAGE_OR_BEFORE && !boot_cpu())
Eric Biederman8ca8d762003-04-22 19:02:15 +0000135 return 0;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000136
Julius Wernerb6cf6422022-02-02 17:21:02 -0800137 state.speed = console_log_level(msg_level);
138 if (state.speed < CONSOLE_LOG_FAST)
Kyösti Mälkkib2d25962014-01-27 15:09:13 +0200139 return 0;
Kyösti Mälkkib2d25962014-01-27 15:09:13 +0200140
Eric Biederman8ca8d762003-04-22 19:02:15 +0000141 spin_lock(&console_lock);
142
Kyösti Mälkki45ddb432019-11-02 14:12:18 +0200143 console_time_run();
144
Julius Wernerb6cf6422022-02-02 17:21:02 -0800145 i = vtxprintf(wrap_putchar, fmt, args, state.as_ptr);
Julius Werner266041f2022-02-03 17:25:44 -0800146 if (LOG_FAST(state))
Kyösti Mälkkie613d702019-02-12 14:16:21 +0200147 console_tx_flush();
Eric Biederman8ca8d762003-04-22 19:02:15 +0000148
Kyösti Mälkki45ddb432019-11-02 14:12:18 +0200149 console_time_stop();
150
Eric Biederman8ca8d762003-04-22 19:02:15 +0000151 spin_unlock(&console_lock);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000152
153 return i;
154}
Kyösti Mälkkib3356bb2014-03-06 16:55:05 +0200155
Nico Huber7cc14ac2021-03-27 20:03:02 +0100156int printk(int msg_level, const char *fmt, ...)
Kyösti Mälkkib3356bb2014-03-06 16:55:05 +0200157{
Kyösti Mälkki7132f252019-02-14 23:08:29 +0200158 va_list args;
159 int i;
160
161 va_start(args, fmt);
Nico Huber7cc14ac2021-03-27 20:03:02 +0100162 i = vprintk(msg_level, fmt, args);
Kyösti Mälkki7132f252019-02-14 23:08:29 +0200163 va_end(args);
164
165 return i;
Kyösti Mälkkib3356bb2014-03-06 16:55:05 +0200166}