coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
printk.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /*
4  * blatantly copied from linux/kernel/printk.c
5  */
6 
8 #include <console/console.h>
9 #include <console/streams.h>
10 #include <console/vtxprintf.h>
11 #include <smp/spinlock.h>
12 #include <smp/node.h>
13 #include <timer.h>
14 
15 DECLARE_SPIN_LOCK(console_lock)
16 
17 #define TRACK_CONSOLE_TIME (!ENV_SMM && CONFIG(HAVE_MONOTONIC_TIMER))
18 
19 static struct mono_time mt_start, mt_stop;
20 static long console_usecs;
21 
22 static void console_time_run(void)
23 {
25  timer_monotonic_get(&mt_start);
26 }
27 
28 static void console_time_stop(void)
29 {
30  if (TRACK_CONSOLE_TIME && boot_cpu()) {
33  }
34 }
35 
37 {
38  if (!TRACK_CONSOLE_TIME)
39  return;
40 
41  printk(BIOS_DEBUG, "BS: " ENV_STRING " times (exec / console): total (unknown) / %ld ms\n",
43 }
44 
46 {
47  if (!TRACK_CONSOLE_TIME)
48  return 0;
49 
50  long elapsed = console_usecs;
51  console_usecs = 0;
52  return elapsed;
53 }
54 
55 void do_putchar(unsigned char byte)
56 {
58  console_tx_byte(byte);
60 }
61 
62 union log_state {
63  void *as_ptr;
64  struct {
67  };
68 };
69 
70 #define LOG_FAST(state) (HAS_ONLY_FAST_CONSOLES || ((state).speed == CONSOLE_LOG_FAST))
71 
72 static void wrap_interactive_printf(const char *fmt, ...)
73 {
74  va_list args;
75  va_start(args, fmt);
77  va_end(args);
78 }
79 
80 static void line_start(union log_state state)
81 {
82  if (state.level > BIOS_LOG_PREFIX_MAX_LEVEL)
83  return;
84 
85  /* Stored consoles just get a single control char marker to save space. If we are in
86  LOG_FAST mode, just write the marker to CBMC and exit -- the rest of this function
87  implements the LOG_ALL case. */
88  unsigned char marker = BIOS_LOG_LEVEL_TO_MARKER(state.level);
89  if (LOG_FAST(state)) {
90  __cbmemc_tx_byte(marker);
91  return;
92  }
94 
95  /* Interactive consoles get a `[DEBUG] ` style readable prefix,
96  and potentially an escape sequence for highlighting. */
97  if (CONFIG(CONSOLE_USE_ANSI_ESCAPES))
99  if (CONFIG(CONSOLE_USE_LOGLEVEL_PREFIX))
101 }
102 
103 static void line_end(union log_state state)
104 {
105  if (CONFIG(CONSOLE_USE_ANSI_ESCAPES) && !LOG_FAST(state))
107 }
108 
109 static void wrap_putchar(unsigned char byte, void *data)
110 {
111  union log_state state = { .as_ptr = data };
112  static bool line_started = false;
113 
114  if (byte == '\n') {
115  line_end(state);
116  line_started = false;
117  } else if (!line_started) {
118  line_start(state);
119  line_started = true;
120  }
121 
122  if (LOG_FAST(state))
123  __cbmemc_tx_byte(byte);
124  else
125  console_tx_byte(byte);
126 }
127 
128 int vprintk(int msg_level, const char *fmt, va_list args)
129 {
130  union log_state state = { .level = msg_level };
131  int i;
132 
133  if (CONFIG(SQUELCH_EARLY_SMP) && ENV_ROMSTAGE_OR_BEFORE && !boot_cpu())
134  return 0;
135 
136  state.speed = console_log_level(msg_level);
137  if (state.speed < CONSOLE_LOG_FAST)
138  return 0;
139 
140  spin_lock(&console_lock);
141 
143 
144  i = vtxprintf(wrap_putchar, fmt, args, state.as_ptr);
145  if (LOG_FAST(state))
147 
149 
150  spin_unlock(&console_lock);
151 
152  return i;
153 }
154 
155 int printk(int msg_level, const char *fmt, ...)
156 {
157  va_list args;
158  int i;
159 
160  va_start(args, fmt);
161  i = vprintk(msg_level, fmt, args);
162  va_end(args);
163 
164  return i;
165 }
#define DECLARE_SPIN_LOCK(x)
Definition: spinlock.h:18
void timer_monotonic_get(struct mono_time *mt)
Definition: arch_timer.c:6
static void __cbmemc_tx_byte(u8 data)
Definition: cbmem_console.h:21
struct @413::@414 args
int boot_cpu(void)
Definition: psp.c:5
void console_interactive_tx_byte(unsigned char byte, void *data_unused)
Definition: console.c:30
void console_tx_flush(void)
Definition: console.c:59
void console_tx_byte(unsigned char byte)
Definition: console.c:53
void console_stored_tx_byte(unsigned char byte, void *data_unused)
Definition: console.c:47
static void wrap_putchar(unsigned char byte, void *data)
Definition: printk.c:109
#define LOG_FAST(state)
Definition: printk.c:70
void console_time_report(void)
Definition: printk.c:36
static long console_usecs
Definition: printk.c:20
#define TRACK_CONSOLE_TIME
Definition: printk.c:17
void do_putchar(unsigned char byte)
Definition: printk.c:55
int vprintk(int msg_level, const char *fmt, va_list args)
Definition: printk.c:128
int printk(int msg_level, const char *fmt,...)
Definition: printk.c:155
static void console_time_stop(void)
Definition: printk.c:28
static struct mono_time mt_start mt_stop
Definition: printk.c:19
static void console_time_run(void)
Definition: printk.c:22
long console_time_get_and_reset(void)
Definition: printk.c:45
static void line_end(union log_state state)
Definition: printk.c:103
static void line_start(union log_state state)
Definition: printk.c:80
static void wrap_interactive_printf(const char *fmt,...)
Definition: printk.c:72
@ CONFIG
Definition: dsi_common.h:201
#define DIV_ROUND_CLOSEST(x, divisor)
Definition: helpers.h:17
#define spin_lock(lock)
Definition: spinlock.h:11
#define spin_unlock(lock)
Definition: spinlock.h:12
#define USECS_PER_MSEC
Definition: timer.h:10
static long mono_time_diff_microseconds(const struct mono_time *t1, const struct mono_time *t2)
Definition: timer.h:105
int console_log_level(int msg_level)
Definition: init.c:33
static const char bios_log_prefix[BIOS_LOG_PREFIX_MAX_LEVEL+1][5]
Definition: loglevel.h:168
#define BIOS_LOG_LEVEL_TO_MARKER(level)
Definition: loglevel.h:215
#define BIOS_LOG_ESCAPE_RESET
Definition: loglevel.h:191
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_LOG_PREFIX_MAX_LEVEL
Definition: loglevel.h:167
#define BIOS_LOG_PREFIX_PATTERN
Definition: loglevel.h:166
#define BIOS_LOG_ESCAPE_PATTERN
Definition: loglevel.h:190
static const char bios_log_escape[BIOS_LOG_PREFIX_MAX_LEVEL+1][8]
Definition: loglevel.h:192
state
Definition: raminit.c:1787
#define ENV_STRING
Definition: rules.h:156
#define ENV_ROMSTAGE_OR_BEFORE
Definition: rules.h:263
#define va_end(v)
Definition: stdarg.h:14
#define va_start(v, l)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: stdarg.h:13
__builtin_va_list va_list
Definition: stdarg.h:16
#define NULL
Definition: stddef.h:19
unsigned char uint8_t
Definition: stdint.h:8
uint8_t level
Definition: printk.c:65
void * as_ptr
Definition: printk.c:63
uint8_t speed
Definition: printk.c:66
int vtxprintf(void(*tx_byte)(unsigned char byte, void *data), const char *fmt, va_list args, void *data)
Definition: vtxprintf.c:102