Patrick Georgi ([email protected]) just uploaded a new patch set to 
gerrit, which you can find at http://review.coreboot.org/1871

-gerrit

commit b5c7768ecadcdda8ab12204fd40b9f153da82027
Author: Patrick Georgi <[email protected]>
Date:   Fri Nov 16 15:05:11 2012 +0100

    Add nvramcui
    
    nvramcui is a small libpayload based utility that provides
    an interactive CMOS editor for pre-boot environments.
    
    Change-Id: I514b8a7682f89d242d1b31b6907cc6bff34da4bf
    Signed-off-by: Patrick Georgi <[email protected]>
---
 payloads/nvramcui/nvramcui.c | 247 +++++++++++++++++++++++++++++++++++++++++++
 payloads/nvramcui/payload.sh |   7 ++
 2 files changed, 254 insertions(+)

diff --git a/payloads/nvramcui/nvramcui.c b/payloads/nvramcui/nvramcui.c
new file mode 100644
index 0000000..e980130
--- /dev/null
+++ b/payloads/nvramcui/nvramcui.c
@@ -0,0 +1,247 @@
+/*
+ * 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;
+       ITEM *cur;
+       
+       /* 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");
+
+       /* 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) {
+               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;
+               }
+               render_form(form);
+       }
+
+       for (i = 0; i < numopts; i++) {
+               char *name = field_buffer(fields[2*i], 0);
+               char *value = field_buffer(fields[2*i+1], 0);
+               set_option_from_string(use_nvram, opttbl, value, name);
+       }
+
+       unpost_form(form);
+       free_form(form);
+       touchwin(stdscr);
+       refresh();
+
+       endwin();
+       /* TODO: reboot */
+       halt();
+}
+
diff --git a/payloads/nvramcui/payload.sh b/payloads/nvramcui/payload.sh
new file mode 100755
index 0000000..57ed38b
--- /dev/null
+++ b/payloads/nvramcui/payload.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# This is a trivial payload compile & find script for abuild
+#
+DIR=`dirname $0`
+lpgcc -o $DIR/nvramcui.elf $DIR/nvramcui.c 2>&1 >/dev/null || exit 1
+echo "$DIR/nvramcui.elf"

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to