diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/libbootmenu/Makefile | 49 | ||||
-rw-r--r-- | lib/libbootmenu/bootmenu.c | 187 | ||||
-rw-r--r-- | lib/libbootmenu/bootmenu.code | 20 | ||||
-rw-r--r-- | lib/libbootmenu/bootmenu.h | 15 | ||||
-rw-r--r-- | lib/libbootmenu/bootmenu.in | 15 |
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) |