Files
system76-coreboot/payloads/nvramcui/nvramcui.c
Lubomir Rintel 68009e98ab nvramcui: don't wait for the first key update to render the form
Flush out the initial screen window and render the form before the first
keypress. It looks overly weird otherwise and is very likely unintended.

Change-Id: I8700e36e608f2ba115359070f75b7dc9f230291e
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Reviewed-on: http://review.coreboot.org/8526
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2015-02-25 21:06:15 +01:00

253 lines
5.9 KiB
C

/*
* This file is part of the coreboot project.
*
* Copyright (C) 2012 secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <string.h>
#include <libpayload.h>
#include <coreboot_tables.h>
#include <curses.h>
#include <menu.h>
#include <form.h>
#ifndef HOSTED
#define HOSTED 0
#endif
static int min(int x, int y)
{
if (x < y)
return x;
return y;
}
static int max(int x, int y)
{
if (x > y)
return x;
return y;
}
void render_form(FORM *form)
{
int y, x, line;
WINDOW *w = form_win(form);
WINDOW *inner_w = form_sub(form);
int numlines = getmaxy(w)-2;
getyx(inner_w, y, x);
line = y - (y % numlines);
WINDOW *der = derwin(w, getmaxy(w)-2, getmaxx(w)-2, 1, 1);
wclear(der);
wrefresh(der);
delwin(der);
copywin(inner_w, w, line, 0, 1, 1, min(numlines, getmaxy(inner_w)-line), 68, 0);
wmove(w, y + 1 - line, x + 1);
wrefresh(w);
}
int main()
{
int ch, done;
/* coreboot data structures */
lib_get_sysinfo();
struct cb_cmos_option_table *opttbl = get_system_option_table();
if (opttbl == NULL) {
printf("Could not find coreboot option table\n");
halt();
}
/* display initialization */
initscr();
keypad(stdscr, TRUE);
cbreak();
noecho();
start_color();
leaveok(stdscr, TRUE);
curs_set(1);
erase();
box(stdscr, 0, 0);
mvaddstr(0, 2, "coreboot configuration utility");
refresh();
/* prep CMOS layout into libcurses data structures */
/* determine number of options, and maximum option name length */
int numopts=0;
int maxlength=0;
struct cb_cmos_entries *option = first_cmos_entry(opttbl);
while (option) {
if ((option->config != 'r') && (strcmp("check_sum", option->name) != 0)) {
maxlength = max(maxlength, strlen(option->name));
numopts++;
}
option = next_cmos_entry(option);
}
if (numopts == 0) {
printf("NO CMOS OPTIONS FOUND. EXITING!!!");
return 1;
}
FIELD **fields = malloc(sizeof(FIELD*)*(2*numopts+1));
int i;
/* walk over options, fetch details */
option = first_cmos_entry(opttbl);
for (i=0;i<numopts;i++) {
while ((option->config == 'r') || (strcmp("check_sum", option->name) == 0)) {
option = next_cmos_entry(option);
}
fields[2*i] = new_field(1, strlen(option->name), i*2, 1, 0, 0);
set_field_buffer(fields[2*i], 0, option->name);
field_opts_off(fields[2*i], O_ACTIVE);
fields[2*i+1] = new_field(1, 40, i*2, maxlength+2, 0, 0);
char *buf = NULL;
int fail = get_option_as_string(use_nvram, opttbl, &buf, option->name);
switch (option->config) {
case 'h': {
set_field_type(fields[2*i+1], TYPE_INTEGER, 0, 0, (1<<option->length)-1);
field_opts_on(fields[2*i+1], O_BLANK);
break;
}
case 's': {
set_max_field(fields[2*i+1], option->length/8);
field_opts_off(fields[2*i+1], O_STATIC);
break;
}
case 'e': {
int numvals = 0;
struct cb_cmos_enums *cmos_enum = first_cmos_enum_of_id(opttbl, option->config_id);
/* if invalid data in CMOS, set buf to first enum */
if (fail && cmos_enum) {
buf = cmos_enum->text;
}
while (cmos_enum) {
numvals++;
cmos_enum = next_cmos_enum_of_id(cmos_enum, option->config_id);
}
char **values = malloc(sizeof(char*)*numvals + 1);
int cnt = 0;
cmos_enum = first_cmos_enum_of_id(opttbl, option->config_id);
while (cmos_enum) {
values[cnt] = cmos_enum->text;
cnt++;
cmos_enum = next_cmos_enum_of_id(cmos_enum, option->config_id);
}
values[cnt] = NULL;
field_opts_off(fields[2*i+1], O_EDIT);
set_field_type(fields[2*i+1], TYPE_ENUM, values, 1, 1);
free(values); // copied by set_field_type
break;
}
default:
break;
}
if (buf) set_field_buffer(fields[2*i+1], 0, buf);
#if HOSTED
// underline is non-trivial on VGA text
set_field_back(fields[2*i+1], A_UNDERLINE);
#endif
field_opts_off(fields[2*i+1], O_BLANK | O_AUTOSKIP | O_NULLOK);
option = next_cmos_entry(option);
}
fields[2*numopts]=NULL;
FORM *form = new_form(fields);
int numlines = min(numopts*2, 16);
WINDOW *w = newwin(numlines+2, 70, 2, 1);
WINDOW *inner_w = newpad(numopts*2, 68);
box(w, 0, 0);
mvwaddstr(w, 0, 2, "Press F1 when done");
set_form_win(form, w);
set_form_sub(form, inner_w);
post_form(form);
done = 0;
while(!done) {
render_form(form);
ch=getch();
if (ch == ERR) continue;
switch (ch) {
case KEY_DOWN:
form_driver(form, REQ_NEXT_FIELD);
break;
case KEY_UP:
form_driver(form, REQ_PREV_FIELD);
break;
case KEY_LEFT:
if (field_type(current_field(form)) == TYPE_ENUM) {
form_driver(form, REQ_PREV_CHOICE);
} else {
form_driver(form, REQ_LEFT_CHAR);
}
break;
case KEY_RIGHT:
if (field_type(current_field(form)) == TYPE_ENUM) {
form_driver(form, REQ_NEXT_CHOICE);
} else {
form_driver(form, REQ_RIGHT_CHAR);
}
break;
case KEY_BACKSPACE:
case '\b':
form_driver(form, REQ_DEL_PREV);
break;
case KEY_DC:
form_driver(form, REQ_DEL_CHAR);
break;
case KEY_F(1):
done=1;
break;
default:
form_driver(form, ch);
break;
}
}
for (i = 0; i < numopts; i++) {
char *name = field_buffer(fields[2*i], 0);
char *value = field_buffer(fields[2*i+1], 0);
char *ptr;
for (ptr = value + strlen (value) - 1;
ptr >= value && *ptr == ' '; ptr--);
ptr[1] = '\0';
set_option_from_string(use_nvram, opttbl, value, name);
}
unpost_form(form);
free_form(form);
touchwin(stdscr);
refresh();
endwin();
/* TODO: reboot */
halt();
}