summaryrefslogtreecommitdiffstats
path: root/commands/boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'commands/boot.c')
-rw-r--r--commands/boot.c111
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