libpayload: increase MAX_ARGC_COUNT
[coreboot.git] / payloads / coreinfo / bootlog_module.c
blob1d990d1d0c6c7b2697d4da8f23cc88382d6ed7ba
1 /*
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.
16 #include "coreinfo.h"
18 #if IS_ENABLED(CONFIG_MODULE_BOOTLOG)
20 #define LINES_SHOWN 19
21 #define TAB_WIDTH 2
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 {
33 u32 size;
34 u32 cursor;
35 u8 body[0];
36 } __attribute__ ((__packed__));
39 static u32 char_width(char c, u32 cursor, u32 screen_width)
41 if (c == '\n') {
42 return screen_width - (cursor % screen_width);
43 } else if (c == '\t') {
44 return TAB_WIDTH;
45 } else if (isprint(c)) {
46 return 1;
49 return 0;
52 static u32 calculate_chars_count(char *str, u32 str_len, u32 screen_width, u32 screen_height)
54 u32 i, count = 0;
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;
65 /* Pad to line end */
66 if (count % screen_width != 0) {
67 count += screen_width - (count % screen_width);
70 return count;
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)
81 u32 cursor = 0;
82 u32 i;
84 for (i = 0; i < str_len && cursor < out_len; i++) {
85 u32 width = char_width(str[i], cursor, screen_width);
86 if (width == 1) {
87 out[cursor++] = str[i];
88 } else if (width > 1) {
89 while (width-- && cursor < out_len) {
90 out[cursor++] = ' ';
95 /* Fill the rest of the out buffer with spaces */
96 while (cursor < out_len) {
97 out[cursor++] = ' ';
100 return 0;
103 static int bootlog_module_init(void)
105 /* Make sure that lib_sysinfo is initialized */
106 int ret = lib_get_sysinfo();
107 if (ret) {
108 return -1;
111 struct cbmem_console *console = lib_sysinfo.cbmem_cons;
112 if (console == NULL) {
113 return -1;
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) {
130 return -2;
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);
137 if (!g_buf) {
138 return -3;
141 if (sanitize_buffer_for_display(buffer, cursor + 1,
142 g_buf, chars_count,
143 SCREEN_X) < 0) {
144 free(g_buf);
145 g_buf = NULL;
146 return -4;
149 /* TODO: Maybe a _cleanup hook where we call free()? */
151 return 0;
154 static int bootlog_module_redraw(WINDOW *win)
156 print_module_title(win, "Coreboot Bootlog");
158 if (!g_buf) {
159 return -1;
162 int x = 0, y = 0;
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);
168 tmp++;
173 return 0;
176 static int bootlog_module_handle(int key)
178 if (!g_buf) {
179 return 0;
182 switch (key) {
183 case KEY_DOWN:
184 g_line++;
185 break;
186 case KEY_UP:
187 g_line--;
188 break;
189 case KEY_NPAGE: /* Page up */
190 g_line -= LINES_SHOWN;
191 break;
192 case KEY_PPAGE: /* Page down */
193 g_line += LINES_SHOWN;
194 break;
197 if (g_line < 0)
198 g_line = 0;
200 if (g_line > g_max_cursor_line)
201 g_line = g_max_cursor_line;
203 return 1;
206 struct coreinfo_module bootlog_module = {
207 .name = "Bootlog",
208 .init = bootlog_module_init,
209 .redraw = bootlog_module_redraw,
210 .handle = bootlog_module_handle,
213 #else
215 struct coreinfo_module bootlog_module = {
218 #endif