aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/libbootmenu/Makefile49
-rw-r--r--lib/libbootmenu/bootmenu.c187
-rw-r--r--lib/libbootmenu/bootmenu.code20
-rw-r--r--lib/libbootmenu/bootmenu.h15
-rw-r--r--lib/libbootmenu/bootmenu.in15
6 files changed, 287 insertions, 1 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 6d9db66..a4d4bb2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,7 @@
# ****************************************************************************/
SUBDIRS = libc libipmi libbootmsg libbases libnvram libelf libhvcall libvirtio \
- libusb libveth libe1k libbcm libnet
+ libusb libveth libe1k libbcm libnet libbootmenu
all: subdirs
diff --git a/lib/libbootmenu/Makefile b/lib/libbootmenu/Makefile
new file mode 100644
index 0000000..156bc8b
--- /dev/null
+++ b/lib/libbootmenu/Makefile
@@ -0,0 +1,49 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2008 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+ifndef TOP
+ TOP = $(shell while ! test -e make.rules; do cd .. ; done; pwd)
+ export TOP
+endif
+include $(TOP)/make.rules
+
+CFLAGS += -I. -I.. -I../libc/include -I$(SLOFCMNDIR) -I$(INCLCMNDIR)
+
+SRCS = bootmenu.c
+
+OBJS = $(SRCS:%.c=%.o)
+
+TARGET = ../libbootmenu.a
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(AR) -rc $@ $(OBJS)
+ $(RANLIB) $@
+
+clean:
+ $(RM) $(TARGET) $(OBJS)
+
+distclean: clean
+ $(RM) Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(RM) Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile
+ $(CC) -M $(CPPFLAGS) $(CFLAGS) $(SRCS) > Makefile.dep
+
+# Include dependency file if available:
+-include Makefile.dep
diff --git a/lib/libbootmenu/bootmenu.c b/lib/libbootmenu/bootmenu.c
new file mode 100644
index 0000000..e5cb4b2
--- /dev/null
+++ b/lib/libbootmenu/bootmenu.c
@@ -0,0 +1,187 @@
+/*****************************************************************************
+ * Boot menu: Displays boot devices and waits for user to select one
+ *
+ * Copyright 2017 Red Hat, Inc.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * Thomas Huth, Red Hat Inc. - initial implementation
+ *****************************************************************************/
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <paflof.h>
+#include <helpers.h>
+#include "bootmenu.h"
+
+#define MAX_DEVS 36 /* Enough for 10 digits + 26 letters */
+#define MAX_ALIAS_LEN 8 /* Maximum length of alias names */
+
+struct bootdev {
+ char alias[MAX_ALIAS_LEN];
+ char *path;
+};
+
+static int nr_devs;
+static struct bootdev bootdevs[MAX_DEVS];
+
+/**
+ * Look up an alias name.
+ * @return The NUL-terminated device tree path (should be released with free()
+ * when it's not required anymore), or NULL if it can't be found.
+ */
+static char *find_alias(char *alias)
+{
+ char *path;
+ long len;
+
+ forth_push((unsigned long)alias);
+ forth_push(strlen(alias));
+ forth_eval("find-alias");
+
+ len = forth_pop();
+ if (!len)
+ return NULL;
+
+ path = malloc(len + 1);
+ if (!path) {
+ puts("Out of memory in find_alias");
+ return NULL;
+ }
+ memcpy(path, (void *)forth_pop(), len);
+ path[len] = '\0';
+
+ return path;
+}
+
+static void bootmenu_populate_devs_alias(const char *alias)
+{
+ int idx;
+
+ for (idx = 0; idx <= 9 && nr_devs < MAX_DEVS; idx++, nr_devs++) {
+ char *cur_alias = bootdevs[nr_devs].alias;
+ if (idx == 0)
+ strcpy(cur_alias, alias);
+ else
+ sprintf(cur_alias, "%s%i", alias, idx);
+ bootdevs[nr_devs].path = find_alias(cur_alias);
+ if (!bootdevs[nr_devs].path)
+ break;
+ }
+}
+
+static void bootmenu_populate_devs(void)
+{
+ bootmenu_populate_devs_alias("cdrom");
+ bootmenu_populate_devs_alias("disk");
+ bootmenu_populate_devs_alias("net");
+}
+
+static void bootmenu_free_devs(void)
+{
+ while (nr_devs-- > 0) {
+ free(bootdevs[nr_devs].path);
+ bootdevs[nr_devs].path = NULL;
+ }
+}
+
+static void bootmenu_show_devs(void)
+{
+ int i;
+
+ for (i = 0; i < nr_devs; i++) {
+ printf("%c) %6s : %s\n", i < 9 ? '1' + i : 'a' + i - 9,
+ bootdevs[i].alias, bootdevs[i].path);
+ }
+}
+
+static bool has_key(void)
+{
+ forth_eval("key?");
+ return forth_pop();
+}
+
+static char get_key(void)
+{
+ forth_eval("key");
+ return forth_pop();
+}
+
+/* Flush pending key presses */
+static void flush_keys(void)
+{
+ uint32_t start;
+
+ start = SLOF_GetTimer();
+ while (SLOF_GetTimer() - start < 10) {
+ if (has_key()) {
+ get_key();
+ start = SLOF_GetTimer();
+ }
+ }
+}
+
+static int bootmenu_get_selection(void)
+{
+ char key = 0;
+ int sel;
+
+ do {
+ sel = -1;
+ if (!has_key())
+ continue;
+ key = get_key();
+ switch (key) {
+ case '0':
+ return -1;
+ case '1' ... '9':
+ sel = key - '1';
+ break;
+ case 'a' ... 'z':
+ sel = key - 'a' + 9;
+ break;
+ case 'A' ... 'Z':
+ sel = key - 'A' + 9;
+ break;
+ default:
+ /* Might be another escape code (F12) ... skip it */
+ flush_keys();
+ break;
+ }
+ } while (sel < 0 || sel >= nr_devs);
+
+ return sel;
+}
+
+void bootmenu(void)
+{
+ int sel;
+
+ bootmenu_populate_devs();
+ if (!nr_devs) {
+ puts("No available boot devices!");
+ return;
+ }
+
+ puts("\nSelect boot device (or press '0' to abort):");
+ bootmenu_show_devs();
+
+ if (has_key()) /* In case the user hammered on F12 */
+ flush_keys();
+
+ sel = bootmenu_get_selection();
+ if (sel < 0) {
+ forth_push(0);
+ } else {
+ forth_push((unsigned long)bootdevs[sel].alias);
+ forth_push(strlen(bootdevs[sel].alias));
+ }
+
+ bootmenu_free_devs();
+}
diff --git a/lib/libbootmenu/bootmenu.code b/lib/libbootmenu/bootmenu.code
new file mode 100644
index 0000000..2a55c09
--- /dev/null
+++ b/lib/libbootmenu/bootmenu.code
@@ -0,0 +1,20 @@
+/*****************************************************************************
+ * Boot menu: Glue code to Forth
+ *
+ * Copyright 2017 Red Hat, Inc.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * Thomas Huth, Red Hat Inc. - initial implementation
+ *****************************************************************************/
+
+#include "bootmenu.h"
+
+// ( -- [str] len|0 )
+PRIM(boot_X2d_menu)
+ bootmenu();
+MIRP
diff --git a/lib/libbootmenu/bootmenu.h b/lib/libbootmenu/bootmenu.h
new file mode 100644
index 0000000..6cef237
--- /dev/null
+++ b/lib/libbootmenu/bootmenu.h
@@ -0,0 +1,15 @@
+/*****************************************************************************
+ * Boot menu definitions
+ *
+ * Copyright 2017 Red Hat, Inc.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * Thomas Huth, Red Hat Inc. - initial implementation
+ *****************************************************************************/
+
+extern void bootmenu(void);
diff --git a/lib/libbootmenu/bootmenu.in b/lib/libbootmenu/bootmenu.in
new file mode 100644
index 0000000..5cb120e
--- /dev/null
+++ b/lib/libbootmenu/bootmenu.in
@@ -0,0 +1,15 @@
+/*****************************************************************************
+ * Boot menu: Definitions for Forth
+ *
+ * Copyright 2017 Red Hat, Inc.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * Thomas Huth, Red Hat Inc. - initial implementation
+ *****************************************************************************/
+
+cod(boot-menu)