/ payloads / coreinfo / coreinfo.c
coreinfo.c
  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  
 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  
 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)
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  
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  
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  
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  
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  
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  
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  
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  
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  }