xref: /aosp_15_r20/external/coreboot/payloads/coreinfo/coreinfo.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include "coreinfo.h"
4 
5 #define KEY_ESC 27
6 
7 extern struct coreinfo_module cpuinfo_module;
8 extern struct coreinfo_module pci_module;
9 extern struct coreinfo_module coreboot_module;
10 extern struct coreinfo_module multiboot_module;
11 extern struct coreinfo_module nvram_module;
12 extern struct coreinfo_module bootlog_module;
13 extern struct coreinfo_module ramdump_module;
14 extern struct coreinfo_module cbfs_module;
15 extern struct coreinfo_module timestamps_module;
16 
17 struct coreinfo_module *system_modules[] = {
18 #if CONFIG(MODULE_CPUINFO)
19 	&cpuinfo_module,
20 #endif
21 #if CONFIG(MODULE_PCI)
22 	&pci_module,
23 #endif
24 #if CONFIG(MODULE_NVRAM)
25 	&nvram_module,
26 #endif
27 #if CONFIG(MODULE_RAMDUMP)
28 	&ramdump_module,
29 #endif
30 };
31 
32 struct coreinfo_module *firmware_modules[] = {
33 #if CONFIG(MODULE_COREBOOT)
34 	&coreboot_module,
35 #endif
36 #if CONFIG(MODULE_MULTIBOOT)
37 	&multiboot_module,
38 #endif
39 #if CONFIG(MODULE_BOOTLOG)
40 	&bootlog_module,
41 #endif
42 #if CONFIG(MODULE_CBFS)
43 	&cbfs_module,
44 #endif
45 #if CONFIG(MODULE_TIMESTAMPS)
46 	&timestamps_module,
47 #endif
48 };
49 
50 struct coreinfo_cat {
51 	char name[15];
52 	int cur;
53 	int count;
54 	struct coreinfo_module **modules;
55 } categories[] = {
56 	{
57 		.name = "System",
58 		.modules = system_modules,
59 		.count = ARRAY_SIZE(system_modules),
60 	},
61 	{
62 		.name = "Firmware",
63 		.modules = firmware_modules,
64 		.count = ARRAY_SIZE(firmware_modules),
65 	}
66 };
67 
68 static WINDOW *modwin, *menuwin;
69 static int curwin;
70 
print_module_title(WINDOW * win,const char * title)71 void print_module_title(WINDOW *win, const char *title)
72 {
73 	int i;
74 
75 	wattrset(win, COLOR_PAIR(2));
76 	mvwprintw(win, 0, 1, title);
77 
78 	wmove(win, 1, 1);
79 	for (i = 0; i < 78; i++)
80 		waddch(win, ACS_HLINE);
81 }
82 
print_submenu(struct coreinfo_cat * cat)83 static void print_submenu(struct coreinfo_cat *cat)
84 {
85 	int i, j;
86 	char menu[80];
87 	char *ptr = menu;
88 
89 	wmove(menuwin, 0, 0);
90 
91 	for (j = 0; j < SCREEN_X; j++)
92 		waddch(menuwin, ' ');
93 
94 	if (!cat->count)
95 		return;
96 
97 	for (i = 0; i < cat->count; i++)
98 		ptr += sprintf(ptr, "[%c: %s] ", 'A' + i,
99 			       cat->modules[i]->name);
100 
101 	mvwprintw(menuwin, 0, 0, menu);
102 }
103 
104 #if CONFIG(SHOW_DATE_TIME)
print_time_and_date(void)105 static void print_time_and_date(void)
106 {
107 	struct tm tm;
108 
109 	while (nvram_updating())
110 		mdelay(10);
111 
112 	rtc_read_clock(&tm);
113 
114 	mvwprintw(menuwin, 1, 57, "%02d/%02d/%04d - %02d:%02d:%02d",
115 		  tm.tm_mon + 1, tm.tm_mday, 1900 + tm.tm_year, tm.tm_hour,
116 		  tm.tm_min, tm.tm_sec);
117 }
118 #endif
119 
print_menu(void)120 static void print_menu(void)
121 {
122 	int j;
123 	char menu[80];
124 	char *ptr = menu;
125 
126 	wmove(menuwin, 1, 0);
127 	for (j = 0; j < SCREEN_X; j++)
128 		waddch(menuwin, ' ');
129 
130 	for (size_t i = 0; i < ARRAY_SIZE(categories); i++) {
131 		if (categories[i].count == 0)
132 			continue;
133 
134 		ptr += sprintf(ptr, "F%zu: %s ", i + 1, categories[i].name);
135 	}
136 
137 	mvwprintw(menuwin, 1, 0, menu);
138 
139 #if CONFIG(SHOW_DATE_TIME)
140 	print_time_and_date();
141 #endif
142 }
143 
center(int row,const char * str)144 static void center(int row, const char *str)
145 {
146 	int j, len = strlen(str);
147 
148 	wmove(stdscr, row, 0);
149 	for (j = 0; j < SCREEN_X; j++)
150 		waddch(stdscr, ' ');
151 
152 	mvprintw(row, (SCREEN_X - len) / 2, str);
153 }
154 
155 /* FIXME: Currently unused. */
156 #if 0
157 static void header(int row, const char *str)
158 {
159 	char buf[SCREEN_X];
160 	char *ptr = buf;
161 	int i;
162 	int len = strlen(str) + 4;
163 
164 	for (i = 0; i < (SCREEN_X - len) / 2; i++)
165 		ptr += sprintf(ptr, "=");
166 
167 	ptr += sprintf(ptr, "[ %s ]", str);
168 
169 	for (i = ((SCREEN_X - len) / 2) + len; i < SCREEN_X; i++)
170 		ptr += sprintf(ptr, "=");
171 
172 	mvprintw(row, 0, buf);
173 }
174 #endif
175 
redraw_module(struct coreinfo_cat * cat)176 static void redraw_module(struct coreinfo_cat *cat)
177 {
178 	if (cat->count == 0)
179 		return;
180 
181 	wclear(modwin);
182 	cat->modules[cat->cur]->redraw(modwin);
183 	wrefresh(modwin);
184 }
185 
handle_category_key(struct coreinfo_cat * cat,int key)186 static void handle_category_key(struct coreinfo_cat *cat, int key)
187 {
188 	if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')) {
189 		int index;
190 		if (key >= 'A' && key <= 'Z') {
191 			index = key - 'A';
192 		} else {
193 			index = key - 'a';
194 		}
195 		if (index < cat->count) {
196 			cat->cur = index;
197 			redraw_module(cat);
198 			return;
199 		}
200 	}
201 
202 	if (cat->count && cat->modules[cat->cur]->handle) {
203 		if (cat->modules[cat->cur]->handle(key))
204 			redraw_module(cat);
205 	}
206 }
207 
print_no_modules_selected(void)208 static void print_no_modules_selected(void)
209 {
210 	int height = getmaxy(stdscr);
211 
212 	for (size_t i = 0; i < ARRAY_SIZE(categories); i++)
213 		if (categories[i].count > 0)
214 			return;
215 
216 	color_set(2, NULL); // White on black
217 	center(height / 2, "No modules selected");
218 }
219 
first_nonempty_category(void)220 static int first_nonempty_category(void)
221 {
222 	for (size_t i = 0; i < ARRAY_SIZE(categories); i++)
223 		if (categories[i].count > 0)
224 			return i;
225 	return 0;
226 }
227 
loop(void)228 static void loop(void)
229 {
230 	int key;
231 
232 	center(0, CONFIG_COREINFO_NAME " " CONFIG_COREINFO_VERSION);
233 	print_no_modules_selected();
234 	refresh();
235 
236 	curwin = first_nonempty_category();
237 	print_menu();
238 	print_submenu(&categories[curwin]);
239 	redraw_module(&categories[curwin]);
240 
241 	halfdelay(10);
242 
243 	while (1) {
244 		int ch = -1;
245 
246 #if CONFIG(SHOW_DATE_TIME)
247 		print_time_and_date();
248 		wrefresh(menuwin);
249 #endif
250 
251 		key = getch();
252 
253 		if (key == ERR)
254 			continue;
255 
256 		if (key >= KEY_F(1) && key <= KEY_F(9))
257 			ch = key - KEY_F(1);
258 		if (key >= '1' && key <= '9')
259 			ch = key - '1';
260 
261 		if (ch >= 0 && (unsigned int)ch <= ARRAY_SIZE(categories)) {
262 			if (ch == ARRAY_SIZE(categories))
263 				continue;
264 			if (categories[ch].count == 0)
265 				continue;
266 
267 			curwin = ch;
268 			print_submenu(&categories[curwin]);
269 			redraw_module(&categories[curwin]);
270 			continue;
271 		}
272 
273 		if (key == KEY_ESC)
274 			return;
275 
276 		handle_category_key(&categories[curwin], key);
277 	}
278 }
279 
main(int argc,char ** argv)280 int main(int argc, char **argv)
281 {
282 	(void)argc;
283 	(void)argv;
284 
285 	int j;
286 
287 	if (CONFIG(LP_USB))
288 		usb_initialize();
289 
290 	initscr();
291 
292 	start_color();
293 	init_pair(1, COLOR_WHITE, COLOR_GREEN);
294 	init_pair(2, COLOR_WHITE, COLOR_BLACK);
295 	init_pair(3, COLOR_BLACK, COLOR_WHITE);
296 
297 	modwin = newwin(SCREEN_Y - 3, SCREEN_X, 1, 0);
298 	menuwin = newwin(2, SCREEN_X, SCREEN_Y - 2, 0);
299 
300 	wattrset(stdscr, COLOR_PAIR(1) | A_BOLD);
301 	wattrset(modwin, COLOR_PAIR(2));
302 	wattrset(menuwin, COLOR_PAIR(1) | A_BOLD);
303 
304 	werase(modwin);
305 
306 	for (size_t i = 0; i < ARRAY_SIZE(categories); i++) {
307 		for (j = 0; j < categories[i].count; j++)
308 			categories[i].modules[j]->init();
309 	}
310 
311 	noecho(); /* don't let curses echo keyboard chars */
312 	keypad(stdscr, TRUE); /* allow KEY_F(n) keys to be seen */
313 	curs_set(0); /* Hide blinking cursor */
314 
315 	loop();
316 
317 	/* reboot */
318 	outb(0x6, 0xcf9);
319 	halt();
320 	return 0;
321 }
322