From cc532a3f733718526898c14f8137118b7d76a5bc Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Aug 2016 12:22:40 +0200 Subject: boot: add framework for redundant boot scenarios There are several use cases where a redundant Linux system is needed. The barebox bootchooser framework provides the building blocks to model different use cases without the need to start from the scratch over and over again. The bootchooser works on abstract boot targets, each with a set of properties and implements an algorithm which selects the highest priority target to boot. See the documentation contained in this patch for more information. Signed-off-by: Sascha Hauer Signed-off-by: Marc Kleine-Budde Signed-off-by: Sascha Hauer --- commands/bootchooser.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 commands/bootchooser.c (limited to 'commands/bootchooser.c') diff --git a/commands/bootchooser.c b/commands/bootchooser.c new file mode 100644 index 0000000000..91938fe551 --- /dev/null +++ b/commands/bootchooser.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012 Jan Luebbe + * Copyright (C) 2015 Marc Kleine-Budde + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DONTTOUCH -2 +#define DEFAULT -1 + +static void target_reset(struct bootchooser_target *target, int priority, int attempts) +{ + printf("Resetting target %s to ", bootchooser_target_name(target)); + + if (priority >= 0) + printf("priority %d", priority); + else if (priority == DEFAULT) + printf("default priority"); + + if (priority > DONTTOUCH && attempts > DONTTOUCH) + printf(", "); + + if (attempts >= 0) + printf("%d attempts", attempts); + else if (attempts == DEFAULT) + printf("default attempts"); + + printf("\n"); + + if (priority > DONTTOUCH) + bootchooser_target_set_priority(target, priority); + if (attempts > DONTTOUCH) + bootchooser_target_set_attempts(target, attempts); +} + +static int do_bootchooser(int argc, char *argv[]) +{ + int opt, ret = 0, i; + struct bootchooser *bootchooser; + struct bootchooser_target *target; + int attempts = DONTTOUCH; + int priority = DONTTOUCH; + int info = 0; + bool done_something = false; + bool last_boot_successful = false; + + while ((opt = getopt(argc, argv, "a:p:is")) > 0) { + switch (opt) { + case 'a': + if (!strcmp(optarg, "default")) + attempts = DEFAULT; + else + attempts = simple_strtoul(optarg, NULL, 0); + break; + case 'p': + if (!strcmp(optarg, "default")) + priority = DEFAULT; + else + priority = simple_strtoul(optarg, NULL, 0); + break; + case 'i': + info = 1; + break; + case 's': + last_boot_successful = true; + break; + default: + return COMMAND_ERROR_USAGE; + } + } + + bootchooser = bootchooser_get(); + if (IS_ERR(bootchooser)) { + printf("No bootchooser found\n"); + return COMMAND_ERROR; + } + + if (last_boot_successful) { + bootchooser_last_boot_successful(); + done_something = true; + } + + if (attempts != DONTTOUCH || priority != DONTTOUCH) { + if (optind < argc) { + for (i = optind; i < argc; i++) { + target = bootchooser_target_by_name(bootchooser, argv[i]); + if (!target) { + printf("No such target: %s\n", argv[i]); + ret = COMMAND_ERROR; + goto out; + } + + target_reset(target, priority, attempts); + } + } else { + bootchooser_for_each_target(bootchooser, target) + target_reset(target, priority, attempts); + } + done_something = true; + } + + if (info) { + bootchooser_info(bootchooser); + done_something = true; + } + + if (!done_something) { + printf("Nothing to do\n"); + ret = COMMAND_ERROR_USAGE; + } +out: + bootchooser_put(bootchooser); + + return ret; +} + +BAREBOX_CMD_HELP_START(bootchooser) +BAREBOX_CMD_HELP_TEXT("Control misc behaviour of the bootchooser") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("Options:") +BAREBOX_CMD_HELP_OPT ("-a [TARGETS]", "set priority of given targets to 'n' or the default priority") +BAREBOX_CMD_HELP_OPT ("-p [TARGETS]", "set remaining attempts of given targets to 'n' or the default attempts") +BAREBOX_CMD_HELP_OPT ("-i", "Show information about the bootchooser") +BAREBOX_CMD_HELP_OPT ("-s", "Mark the last boot successful") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(bootchooser) + .cmd = do_bootchooser, + BAREBOX_CMD_DESC("bootchooser control") + BAREBOX_CMD_GROUP(CMD_GRP_MISC) + BAREBOX_CMD_HELP(cmd_bootchooser_help) +BAREBOX_CMD_END -- cgit v1.2.3