2 * This file is part of the coreinfo project.
4 * Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
18 #if IS_ENABLED(CONFIG_MODULE_BOOTLOG)
20 #define LINES_SHOWN 19
24 /* Globals that are used for tracking screen state */
25 static char *g_buf
= NULL
;
26 static s32 g_line
= 0;
27 static s32 g_lines_count
= 0;
28 static s32 g_max_cursor_line
= 0;
31 /* Copied from libpayload/drivers/cbmem_console.c */
32 struct cbmem_console
{
38 #define CURSOR_MASK ((1 << 28) - 1)
39 #define OVERFLOW (1 << 31)
42 static u32
char_width(char c
, u32 cursor
, u32 screen_width
)
45 return screen_width
- (cursor
% screen_width
);
46 } else if (c
== '\t') {
48 } else if (isprint(c
)) {
55 static u32
calculate_chars_count(char *str
, u32 str_len
, u32 screen_width
, u32 screen_height
)
59 for (i
= 0; i
< str_len
; i
++) {
60 count
+= char_width(str
[i
], count
, screen_width
);
63 /* Ensure that 'count' can occupy at least the whole screen */
64 if (count
< screen_width
* screen_height
) {
65 count
= screen_width
* screen_height
;
69 if (count
% screen_width
!= 0) {
70 count
+= screen_width
- (count
% screen_width
);
77 * This method takes an input buffer and sanitizes it for display, which means:
78 * - '\n' is converted to spaces until end of line
79 * - Tabs are converted to spaces of size TAB_WIDTH
80 * - Only printable characters are preserved
82 static int sanitize_buffer_for_display(char *str
, u32 str_len
, char *out
, u32 out_len
, u32 screen_width
)
87 for (i
= 0; i
< str_len
&& cursor
< out_len
; i
++) {
88 u32 width
= char_width(str
[i
], cursor
, screen_width
);
90 out
[cursor
++] = str
[i
];
91 } else if (width
> 1) {
92 while (width
-- && cursor
< out_len
) {
98 /* Fill the rest of the out buffer with spaces */
99 while (cursor
< out_len
) {
106 static int bootlog_module_init(void)
108 /* Make sure that lib_sysinfo is initialized */
109 int ret
= lib_get_sysinfo();
114 struct cbmem_console
*console
= lib_sysinfo
.cbmem_cons
;
115 if (console
== NULL
) {
118 /* Extract console information */
119 char *buffer
= (char *)(&(console
->body
));
120 u32 size
= console
->size
;
121 u32 cursor
= console
->cursor
& CURSOR_MASK
;
123 /* The cursor may be bigger than buffer size with older console code */
124 if (cursor
>= size
) {
128 /* Calculate how much characters will be displayed on screen */
129 u32 chars_count
= calculate_chars_count(buffer
, cursor
, SCREEN_X
, LINES_SHOWN
);
130 u32 overflow_chars_count
= 0;
131 if (console
->cursor
& OVERFLOW
) {
132 overflow_chars_count
= calculate_chars_count(buffer
+ cursor
,
133 size
- cursor
, SCREEN_X
, LINES_SHOWN
);
136 /* Sanity check, chars_count must be padded to full line */
137 if (chars_count
% SCREEN_X
|| overflow_chars_count
% SCREEN_X
) {
141 g_lines_count
= (chars_count
+ overflow_chars_count
) / SCREEN_X
;
142 g_max_cursor_line
= MAX(g_lines_count
- 1 - LINES_SHOWN
, 0);
144 g_buf
= malloc(chars_count
);
149 if (console
->cursor
& OVERFLOW
) {
150 if (sanitize_buffer_for_display(buffer
+ cursor
, size
- cursor
,
151 g_buf
, overflow_chars_count
, SCREEN_X
) < 0) {
155 if (sanitize_buffer_for_display(buffer
, cursor
,
156 g_buf
+ overflow_chars_count
,
157 chars_count
, SCREEN_X
) < 0) {
161 /* TODO: Maybe a _cleanup hook where we call free()? */
171 static int bootlog_module_redraw(WINDOW
*win
)
173 print_module_title(win
, "coreboot Bootlog");
180 char *tmp
= g_buf
+ g_line
* SCREEN_X
;
182 for (y
= 0; y
< LINES_SHOWN
; y
++) {
183 for (x
= 0; x
< SCREEN_X
; x
++) {
184 mvwaddch(win
, y
+ 2, x
, *tmp
);
193 static int bootlog_module_handle(int key
)
206 case KEY_NPAGE
: /* Page up */
207 g_line
-= LINES_SHOWN
;
209 case KEY_PPAGE
: /* Page down */
210 g_line
+= LINES_SHOWN
;
217 if (g_line
> g_max_cursor_line
)
218 g_line
= g_max_cursor_line
;
223 struct coreinfo_module bootlog_module
= {
225 .init
= bootlog_module_init
,
226 .redraw
= bootlog_module_redraw
,
227 .handle
= bootlog_module_handle
,
232 struct coreinfo_module bootlog_module
= {