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
{
36 } __attribute__ ((__packed__
));
39 static u32
char_width(char c
, u32 cursor
, u32 screen_width
)
42 return screen_width
- (cursor
% screen_width
);
43 } else if (c
== '\t') {
45 } else if (isprint(c
)) {
52 static u32
calculate_chars_count(char *str
, u32 str_len
, u32 screen_width
, u32 screen_height
)
56 for (i
= 0; i
< str_len
; i
++) {
57 count
+= char_width(str
[i
], count
, screen_width
);
60 /* Ensure that 'count' can occupy at least the whole screen */
61 if (count
< screen_width
* screen_height
) {
62 count
= screen_width
* screen_height
;
66 if (count
% screen_width
!= 0) {
67 count
+= screen_width
- (count
% screen_width
);
74 * This method takes an input buffer and sanitizes it for display, which means:
75 * - '\n' is converted to spaces until end of line
76 * - Tabs are converted to spaces of size TAB_WIDTH
77 * - Only printable characters are preserved
79 static int sanitize_buffer_for_display(char *str
, u32 str_len
, char *out
, u32 out_len
, u32 screen_width
)
84 for (i
= 0; i
< str_len
&& cursor
< out_len
; i
++) {
85 u32 width
= char_width(str
[i
], cursor
, screen_width
);
87 out
[cursor
++] = str
[i
];
88 } else if (width
> 1) {
89 while (width
-- && cursor
< out_len
) {
95 /* Fill the rest of the out buffer with spaces */
96 while (cursor
< out_len
) {
103 static int bootlog_module_init(void)
105 /* Make sure that lib_sysinfo is initialized */
106 int ret
= lib_get_sysinfo();
111 struct cbmem_console
*console
= lib_sysinfo
.cbmem_cons
;
112 if (console
== NULL
) {
115 /* Extract console information */
116 char *buffer
= (char *)(&(console
->body
));
117 u32 buffer_size
= console
->size
;
118 u32 cursor
= console
->cursor
;
120 /* The cursor may be bigger than buffer size when the buffer is full */
121 if (cursor
>= buffer_size
) {
122 cursor
= buffer_size
- 1;
125 /* Calculate how much characters will be displayed on screen */
126 u32 chars_count
= calculate_chars_count(buffer
, cursor
+ 1, SCREEN_X
, LINES_SHOWN
);
128 /* Sanity check, chars_count must be padded to full line */
129 if (chars_count
% SCREEN_X
!= 0) {
133 g_lines_count
= chars_count
/ SCREEN_X
;
134 g_max_cursor_line
= MAX(g_lines_count
- 1 - LINES_SHOWN
, 0);
136 g_buf
= malloc(chars_count
);
141 if (sanitize_buffer_for_display(buffer
, cursor
+ 1,
149 /* TODO: Maybe a _cleanup hook where we call free()? */
154 static int bootlog_module_redraw(WINDOW
*win
)
156 print_module_title(win
, "Coreboot Bootlog");
163 char *tmp
= g_buf
+ g_line
* SCREEN_X
;
165 for (y
= 0; y
< LINES_SHOWN
; y
++) {
166 for (x
= 0; x
< SCREEN_X
; x
++) {
167 mvwaddch(win
, y
+ 2, x
, *tmp
);
176 static int bootlog_module_handle(int key
)
189 case KEY_NPAGE
: /* Page up */
190 g_line
-= LINES_SHOWN
;
192 case KEY_PPAGE
: /* Page down */
193 g_line
+= LINES_SHOWN
;
200 if (g_line
> g_max_cursor_line
)
201 g_line
= g_max_cursor_line
;
206 struct coreinfo_module bootlog_module
= {
208 .init
= bootlog_module_init
,
209 .redraw
= bootlog_module_redraw
,
210 .handle
= bootlog_module_handle
,
215 struct coreinfo_module bootlog_module
= {