diff options
Diffstat (limited to 'commands/boot.c')
-rw-r--r-- | commands/boot.c | 111 |
1 files changed, 65 insertions, 46 deletions
diff --git a/commands/boot.c b/commands/boot.c index 0257b3dd4f..e4699520e8 100644 --- a/commands/boot.c +++ b/commands/boot.c @@ -1,15 +1,4 @@ -/* - * 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. - * - */ +// SPDX-License-Identifier: GPL-2.0-or-later #include <globalvar.h> #include <command.h> @@ -21,15 +10,32 @@ #include <linux/stat.h> +static char *next_argv(void *context) +{ + char ***argv = context; + char *next = **argv; + (*argv)++; + return next; +} + +static char *next_word(void *context) +{ + return strsep(context, " "); +} + static int do_boot(int argc, char *argv[]) { char *freep = NULL; int opt, ret = 0, do_list = 0, do_menu = 0; - int i, dryrun = 0, verbose = 0, timeout = -1; + int dryrun = 0, verbose = 0, timeout = -1; + unsigned default_menu_entry = 0; struct bootentries *entries; struct bootentry *entry; + void *handle; + const char *name; + char *(*next)(void *); - while ((opt = getopt(argc, argv, "vldmt:w:")) > 0) { + while ((opt = getopt(argc, argv, "vldmM:t:w:")) > 0) { switch (opt) { case 'v': verbose++; @@ -38,8 +44,18 @@ static int do_boot(int argc, char *argv[]) do_list = 1; break; case 'd': - dryrun = 1; + dryrun++; break; + case 'M': + /* To simplify scripting, an empty string is treated as 1 */ + if (*optarg == '\0') { + default_menu_entry = 1; + } else { + ret = kstrtouint(optarg, 0, &default_menu_entry); + if (ret) + return ret; + } + fallthrough; case 'm': do_menu = 1; break; @@ -54,56 +70,57 @@ static int do_boot(int argc, char *argv[]) } } - entries = bootentries_alloc(); - if (optind < argc) { - for (i = optind; i < argc; i++) { - ret = bootentry_create_from_name(entries, argv[i]); - if (ret <= 0) - printf("Nothing bootable found on '%s'\n", argv[i]); - } + handle = &argv[optind]; + next = next_argv; } else { const char *def; - char *sep, *name; def = getenv("global.boot.default"); if (!def) return 0; - sep = freep = xstrdup(def); + handle = freep = xstrdup(def); + next = next_word; + } + + entries = bootentries_alloc(); + + while ((name = next(&handle)) != NULL) { + if (!*name) + continue; + ret = bootentry_create_from_name(entries, name); + if (ret <= 0) + printf("Nothing bootable found on '%s'\n", name); + + if (do_list || do_menu) + continue; - while ((name = strsep(&sep, " ")) != NULL) { - ret = bootentry_create_from_name(entries, name); - if (ret <= 0) - printf("Nothing bootable found on '%s'\n", name); + bootentries_for_each_entry(entries, entry) { + ret = boot_entry(entry, verbose, dryrun); + if (!ret) + goto out; } - free(freep); + bootentries_free(entries); + entries = bootentries_alloc(); } if (list_empty(&entries->entries)) { printf("Nothing bootable found\n"); - return COMMAND_ERROR; - } - - if (do_list) { - bootsources_list(entries); + ret = COMMAND_ERROR; goto out; } - if (do_menu) { - bootsources_menu(entries, timeout); - goto out; - } - - bootentries_for_each_entry(entries, entry) { - ret = boot_entry(entry, verbose, dryrun); - if (!ret) - break; - } + if (do_list) + bootsources_list(entries); + else if (do_menu) + bootsources_menu(entries, default_menu_entry, timeout); + ret = 0; out: bootentries_free(entries); + free(freep); return ret; } @@ -116,6 +133,7 @@ BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("BOOTSRC can be:") BAREBOX_CMD_HELP_TEXT("- a filename under /env/boot/") BAREBOX_CMD_HELP_TEXT("- a full path to a boot script") +BAREBOX_CMD_HELP_TEXT("- a full path to a bootspec entry") BAREBOX_CMD_HELP_TEXT("- a device name") BAREBOX_CMD_HELP_TEXT("- a partition name under /dev/") BAREBOX_CMD_HELP_TEXT("- a full path to a directory which") @@ -127,9 +145,10 @@ BAREBOX_CMD_HELP_TEXT("one succeeds.") BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-v","Increase verbosity") -BAREBOX_CMD_HELP_OPT ("-d","Dryrun. See what happens but do no actually boot") +BAREBOX_CMD_HELP_OPT ("-d","Dryrun. See what happens but do no actually boot (pass twice to run scripts)") BAREBOX_CMD_HELP_OPT ("-l","List available boot sources") BAREBOX_CMD_HELP_OPT ("-m","Show a menu with boot options") +BAREBOX_CMD_HELP_OPT ("-M INDEX","Show a menu with boot options with entry INDEX preselected") BAREBOX_CMD_HELP_OPT ("-w SECS","Start watchdog with timeout SECS before booting") BAREBOX_CMD_HELP_OPT ("-t SECS","specify timeout in SECS") BAREBOX_CMD_HELP_END @@ -137,7 +156,7 @@ BAREBOX_CMD_HELP_END BAREBOX_CMD_START(boot) .cmd = do_boot, BAREBOX_CMD_DESC("boot from script, device, ...") - BAREBOX_CMD_OPTS("[-vdlmwt] [BOOTSRC...]") + BAREBOX_CMD_OPTS("[-vdlmMwt] [BOOTSRC...]") BAREBOX_CMD_GROUP(CMD_GRP_BOOT) BAREBOX_CMD_HELP(cmd_boot_help) BAREBOX_CMD_END |