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