Documentation/releases: Update 4.15 release notes
[coreboot.git] / payloads / nvramcui / nvramcui.c
blobdb3e522d605f9d296c92f3db8716d319e57080dd
1 /*
3 * Copyright (C) 2012 secunet Security Networks AG
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <coreboot_tables.h>
16 #include <libpayload.h>
18 #include <curses.h>
19 #include <form.h>
20 #include <menu.h>
22 #ifndef HOSTED
23 #define HOSTED 0
24 #endif
26 static int min(int x, int y)
28 if (x < y)
29 return x;
30 return y;
33 static int max(int x, int y)
35 if (x > y)
36 return x;
37 return y;
40 static void render_form(FORM *form)
42 int y, x, line;
43 WINDOW *w = form_win(form);
44 WINDOW *inner_w = form_sub(form);
45 int numlines = getmaxy(w) - 2;
46 getyx(inner_w, y, x);
47 line = y - (y % numlines);
48 WINDOW *der = derwin(w, getmaxy(w) - 2, getmaxx(w) - 2, 1, 1);
49 wclear(der);
50 wrefresh(der);
51 delwin(der);
52 copywin(inner_w, w, line, 0, 1, 1,
53 min(numlines, getmaxy(inner_w) - line), 68, 0);
54 wmove(w, y + 1 - line, x + 1);
55 wrefresh(w);
58 /* determine number of options, and maximum option name length */
59 static int count_cmos_options(struct cb_cmos_entries *option, int *numopts,
60 int *maxlength)
62 int n_opts = 0;
63 int max_l = 0;
65 while (option) {
66 if ((option->config != 'r') &&
67 (strcmp("check_sum", (char *)option->name) != 0)) {
68 max_l = max(max_l, strlen((char *)option->name));
69 n_opts++;
72 option = next_cmos_entry(option);
75 if (n_opts == 0) {
76 printf("NO CMOS OPTIONS FOUND. EXITING!!!");
77 return -1;
80 *numopts = n_opts;
81 *maxlength = max_l;
83 return 0;
87 /* walk over options, fetch details */
88 static void cmos_walk_options(struct cb_cmos_option_table *opttbl,
89 FIELD **fields, int numopts, int maxlength)
91 struct cb_cmos_entries *option = first_cmos_entry(opttbl);
92 int i;
94 for (i = 0; i < numopts; i++) {
95 while ((option->config == 'r') ||
96 (strcmp("check_sum", (char *)option->name) == 0)) {
97 option = next_cmos_entry(option);
99 fields[2 * i] =
100 new_field(1, strlen((char *)option->name), i * 2, 1, 0, 0);
101 set_field_buffer(fields[2 * i], 0, (char *)option->name);
102 field_opts_off(fields[2 * i], O_ACTIVE);
104 fields[2 * i + 1] =
105 new_field(1, 40, i * 2, maxlength + 2, 0, 0);
106 char *buf = NULL;
107 int fail =
108 get_option_as_string(use_nvram, opttbl, &buf, (char *)option->name);
109 switch (option->config) {
110 case 'h': {
111 set_field_type(fields[2 * i + 1], TYPE_INTEGER, 0, 0,
112 (1 << option->length) - 1);
113 field_opts_on(fields[2 * i + 1], O_BLANK);
114 break;
116 case 's': {
117 set_max_field(fields[2 * i + 1], option->length / 8);
118 field_opts_off(fields[2 * i + 1], O_STATIC);
119 break;
121 case 'e': {
122 int numvals = 0;
123 struct cb_cmos_enums *cmos_enum =
124 first_cmos_enum_of_id(opttbl, option->config_id);
126 /* if invalid data in CMOS, set buf to first enum */
127 if (fail && cmos_enum) {
128 buf = (char *)cmos_enum->text;
131 while (cmos_enum) {
132 numvals++;
133 cmos_enum = next_cmos_enum_of_id(
134 cmos_enum, option->config_id);
137 char **values = malloc(sizeof(char *) * (numvals + 1));
138 int cnt = 0;
140 cmos_enum =
141 first_cmos_enum_of_id(opttbl, option->config_id);
142 while (cmos_enum) {
143 values[cnt] = (char *)cmos_enum->text;
144 cnt++;
145 cmos_enum = next_cmos_enum_of_id(
146 cmos_enum, option->config_id);
148 values[cnt] = NULL;
149 field_opts_off(fields[2 * i + 1], O_EDIT);
150 set_field_type(fields[2 * i + 1], TYPE_ENUM, values, 1,
152 free(values); // copied by set_field_type
153 break;
155 default:
156 break;
158 if (buf)
159 set_field_buffer(fields[2 * i + 1], 0, buf);
160 #if HOSTED
161 // underline is non-trivial on VGA text
162 set_field_back(fields[2 * i + 1], A_UNDERLINE);
163 #endif
164 field_opts_off(fields[2 * i + 1],
165 O_BLANK | O_AUTOSKIP | O_NULLOK);
167 option = next_cmos_entry(option);
170 fields[2 * numopts] = NULL;
173 int main(void)
175 int ch, done;
176 int i;
178 if (CONFIG(LP_USB))
179 usb_initialize();
181 /* coreboot data structures */
182 lib_get_sysinfo();
184 struct cb_cmos_option_table *opttbl = get_system_option_table();
186 if (opttbl == NULL) {
187 printf("Could not find coreboot option table.\n");
188 halt();
191 /* prep CMOS layout into libcurses data structures */
193 struct cb_cmos_entries *option = first_cmos_entry(opttbl);
194 int numopts = 0;
195 int maxlength = 0;
197 count_cmos_options(option, &numopts, &maxlength);
199 FIELD **fields = malloc(sizeof(FIELD *) * (2 * numopts + 1));
201 cmos_walk_options(opttbl, fields, numopts, maxlength);
203 /* display initialization */
204 initscr();
205 keypad(stdscr, TRUE);
206 cbreak();
207 noecho();
209 if (start_color()) {
210 assume_default_colors(COLOR_BLUE, COLOR_CYAN);
212 leaveok(stdscr, TRUE);
213 curs_set(1);
215 erase();
216 box(stdscr, 0, 0);
217 mvaddstr(0, 2, "coreboot configuration utility");
218 refresh();
220 FORM *form = new_form(fields);
221 int numlines = min(numopts * 2, 16);
222 WINDOW *w = newwin(numlines + 2, 70, 2, 1);
223 WINDOW *inner_w = newpad(numopts * 2, 68);
224 box(w, 0, 0);
225 mvwaddstr(w, 0, 2, "Press F1 when done");
226 set_form_win(form, w);
227 set_form_sub(form, inner_w);
228 post_form(form);
230 done = 0;
231 while (!done) {
232 render_form(form);
233 ch = getch();
234 if (ch == ERR)
235 continue;
236 switch (ch) {
237 case KEY_DOWN:
238 form_driver(form, REQ_NEXT_FIELD);
239 break;
240 case KEY_UP:
241 form_driver(form, REQ_PREV_FIELD);
242 break;
243 case KEY_LEFT:
244 if (field_type(current_field(form)) == TYPE_ENUM) {
245 form_driver(form, REQ_PREV_CHOICE);
246 } else {
247 form_driver(form, REQ_LEFT_CHAR);
249 break;
250 case KEY_RIGHT:
251 if (field_type(current_field(form)) == TYPE_ENUM) {
252 form_driver(form, REQ_NEXT_CHOICE);
253 } else {
254 form_driver(form, REQ_RIGHT_CHAR);
256 break;
257 case KEY_BACKSPACE:
258 case '\b':
259 form_driver(form, REQ_DEL_PREV);
260 break;
261 case KEY_DC:
262 form_driver(form, REQ_DEL_CHAR);
263 break;
264 case KEY_F(1):
265 done = 1;
266 break;
267 default:
268 form_driver(form, ch);
269 break;
273 endwin();
275 for (i = 0; i < numopts; i++) {
276 char *name = field_buffer(fields[2 * i], 0);
277 char *value = field_buffer(fields[2 * i + 1], 0);
278 char *ptr;
279 for (ptr = value + strlen(value) - 1;
280 ptr >= value && *ptr == ' '; ptr--)
282 ptr[1] = '\0';
283 set_option_from_string(use_nvram, opttbl, value, name);
286 unpost_form(form);
287 free_form(form);
289 /* reboot */
290 outb(0x6, 0xcf9);
291 halt();