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 ×tamps_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