[PATCH 2/2] add boot_menu command support
Jean-Christophe PLAGNIOL-VILLARD
plagnioj at jcrosoft.com
Fri Oct 28 05:37:40 EDT 2011
this just contain the bootmenu for boot_config can not yet boot for real
this will allow to create a boot menu from a dtb file that can be provided
by the OS to show a list a boot option
an example a file is in Documentation/bootsec.cfg
you can test using sandbox
# ./barebox -i Documentation/bootsec.dtb
add file Documentation/bootsec.dtb()
barebox 2011.10.0-00119-gad62fdb-dirty (Oct 15 2011 - 11:38:46)
Board: sandbox
Malloc space: 0x7f679f24b010 -> 0x7f679fa4b010 (size 8 MB)
Open /dev/env0 No such file or directory
no valid environment found on /dev/env0. Using default environment
running /env/bin/init...
barebox:/ boot_config -f /dev/fd0
barebox:/ boot_menu
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
---
commands/Kconfig | 5 +
commands/Makefile | 1 +
commands/boot_menu.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 240 insertions(+), 0 deletions(-)
create mode 100644 commands/boot_menu.c
diff --git a/commands/Kconfig b/commands/Kconfig
index 7980ab7..7d906c0 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -80,6 +80,11 @@ config CMD_BOOT_CONFIG_MANAGEMENT
depends on CMD_BOOT_CONFIG
prompt "boot config management"
+config CMD_BOOT_MENU
+ tristate
+ depends on BOOT_CONFIG
+ prompt "boot menu"
+
config CMD_LOGIN
tristate
select PASSWORD
diff --git a/commands/Makefile b/commands/Makefile
index a832302..b7ca49c 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -59,3 +59,4 @@ obj-$(CONFIG_CMD_USB) += usb.o
obj-$(CONFIG_CMD_TIME) += time.o
obj-$(CONFIG_CMD_OFTREE) += oftree.o
obj-$(CONFIG_CMD_BOOT_CONFIG) += boot_config.o
+obj-$(CONFIG_CMD_BOOT_MENU) += boot_menu.o
diff --git a/commands/boot_menu.c b/commands/boot_menu.c
new file mode 100644
index 0000000..3e09a29
--- /dev/null
+++ b/commands/boot_menu.c
@@ -0,0 +1,234 @@
+/*
+ * (C) Copyright 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <readkey.h>
+#include <menu.h>
+#include <getopt.h>
+#include <errno.h>
+#include <linux/err.h>
+#include <libfdt.h>
+#include <fs.h>
+#include <asm/byteorder.h>
+#include <boot_config.h>
+
+static struct menu *boot_menu;
+static int debug;
+
+struct boot_menu_entry {
+ struct boot_config *config;
+ struct menu_entry entry;
+};
+
+static void print_boot_entry_data(struct boot_config_data *bed)
+{
+ if (bed->format)
+ printf("format = '%s'\n", bed->format);
+ printf("dev = '%s'\n", bed->dev);
+ printf("fs = '%s'\n", bed->fs);
+ printf("path = '%s'\n", bed->path);
+}
+
+static void boot_menu_action(struct menu *m, struct menu_entry *me)
+{
+ struct boot_menu_entry *e = container_of(me, struct boot_menu_entry, entry);
+ struct boot_config_var *v;
+
+ if (debug) {
+ printf("Boot '%s'\n", me->display);
+ v = boot_config_var_get_by_name(e->config, "cmdline");
+ printf("cmdline = '%s'\n", v->value);
+
+ v = boot_config_var_get_by_name(e->config, "splash");
+ if (v)
+ printf("splash = '%s'\n", v->value);
+
+ printf("[Kernel]\n");
+ print_boot_entry_data(e->config->kernel);
+
+ if (e->config->initrd) {
+ printf("[Initrd]\n");
+ print_boot_entry_data(e->config->initrd);
+ }
+
+ if (e->config->fdt) {
+ printf("[fdt]\n");
+ print_boot_entry_data(e->config->fdt);
+ }
+ }
+
+ boot_config_set_env(e->config);
+}
+
+static void boot_menu_entry_free(struct menu_entry *me)
+{
+ struct boot_menu_entry *e = container_of(me, struct boot_menu_entry, entry);
+
+ free(e);
+}
+
+static int menu_set_selected_config(const char* name)
+{
+ struct menu_entry* me;
+ struct boot_menu_entry *e;
+
+ list_for_each_entry(me, &boot_menu->entries, list) {
+ e = container_of(me, struct boot_menu_entry, entry);
+
+ if (strcmp(e->config->name, name) == 0) {
+ menu_set_selected_entry(boot_menu, me);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int boot_menu_add_entry(struct boot_config *bc)
+{
+ struct boot_menu_entry *e = calloc(1, sizeof(*e));
+ struct boot_config_var *v;
+ int ret;
+
+ if (!e)
+ return -ENOMEM;
+
+ if (debug)
+ printf("Boot '%s'\n", bc->name);
+
+ v = boot_config_var_get_by_name(e->config, "description");
+ if (v)
+ e->entry.display = v->value;
+ else
+ e->entry.display = bc->name;
+ e->entry.action = boot_menu_action;
+ e->entry.free = boot_menu_entry_free;
+ e->entry.type = 0;
+ e->entry.non_re_ent = 1;
+ e->config = bc;
+
+ if (!e->entry.display) {
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ ret = menu_add_entry(boot_menu, &e->entry);
+ if (ret)
+ goto err_free;
+
+ return 0;
+err_free:
+ boot_menu_entry_free(&e->entry);
+ return ret;
+}
+
+static void boot_menu_populate(void)
+{
+ struct list_head *configs = boot_config_get_configs();
+ struct boot_config* bc;
+
+ list_for_each_entry(bc, configs, list) {
+ boot_menu_add_entry(bc);
+ }
+}
+
+static int do_boot_menu(struct command *cmdtp, int argc, char *argv[])
+{
+ int opt;
+ char* prop;
+ uint32_t bootdelay;
+ struct menu_entry *me;
+ int ret = COMMAND_ERROR_USAGE;
+ struct boot_config *default_boot;
+
+ debug = 0;
+
+ while((opt = getopt(argc, argv, "d")) > 0) {
+ switch(opt) {
+ case 'd':
+ debug = 1;
+ break;
+ }
+ }
+
+ boot_menu = menu_alloc();
+ boot_menu->name = strdup("boot");
+
+ boot_menu->display = strdup("description");
+
+ ret = menu_add(boot_menu);
+
+ prop = boot_config_get_description();
+ if (!prop)
+ prop = boot_menu->name;
+ boot_menu->display = strdup(prop);
+
+ boot_menu_populate();
+
+ default_boot = boot_config_get_default_boot();
+ if (default_boot) {
+ if (debug)
+ printf("default config %s\n", default_boot->name);
+
+ menu_set_selected_config(default_boot->name);
+ }
+ bootdelay = boot_config_get_bootdelay();
+ if (bootdelay != -1) {
+ if (debug)
+ printf("auto boot in %ds\n", bootdelay);
+ menu_set_auto_select(boot_menu, bootdelay);
+ } else {
+ boot_menu->auto_select = -1;
+ }
+
+ me = menu_add_command_entry(boot_menu, "shell", "exit", 0);
+ me->non_re_ent = 1;
+
+ me = menu_add_command_entry(boot_menu, "reset", "reset", 0);
+
+ if (debug) {
+ printf("Press any key to go to the Menu\n");
+ getc();
+ }
+
+ menu_show(boot_menu);
+
+ ret = 0;
+
+exit_add:
+ menu_remove(boot_menu);
+exit:
+ menu_free(boot_menu);
+ return ret;
+}
+
+static const __maybe_unused char cmd_boot_menu_help[] =
+"Usage: boot_menu [OPTION]... \n"
+"Boot Menu\n"
+" -d debug\n";
+
+BAREBOX_CMD_START(boot_menu)
+ .cmd = do_boot_menu,
+ .usage = "Boot Menu",
+ BAREBOX_CMD_HELP(cmd_boot_menu_help)
+BAREBOX_CMD_END
--
1.7.7
More information about the barebox
mailing list