summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sandbox/os/common.c2
-rw-r--r--commands/timeout.c2
-rw-r--r--common/console.c52
-rw-r--r--common/console_countdown.c19
-rw-r--r--common/hush.c3
-rw-r--r--common/parser.c1
-rw-r--r--common/startup.c188
-rw-r--r--defaultenv/defaultenv-2-base/bin/init77
-rw-r--r--include/common.h4
-rw-r--r--include/console.h3
-rw-r--r--include/console_countdown.h2
11 files changed, 246 insertions, 107 deletions
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index 665e8194ef..a7ea8f2d3b 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -94,7 +94,7 @@ int linux_tstc(int fd)
return 0;
}
-int ctrlc(void)
+int arch_ctrlc(void)
{
char chr;
diff --git a/commands/timeout.c b/commands/timeout.c
index d197cedd8b..db88900287 100644
--- a/commands/timeout.c
+++ b/commands/timeout.c
@@ -61,7 +61,7 @@ static int do_timeout(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
timeout = simple_strtoul(argv[optind], NULL, 0);
- ret = console_countdown(timeout, flags, str);
+ ret = console_countdown(timeout, flags, NULL, str);
if (varname && str[0])
setenv(varname, str);
diff --git a/common/console.c b/common/console.c
index 47ccf2e54d..406722a1da 100644
--- a/common/console.c
+++ b/common/console.c
@@ -574,18 +574,60 @@ void console_flush(void)
}
EXPORT_SYMBOL(console_flush);
-#ifndef ARCH_HAS_CTRLC
+static int ctrlc_abort;
+static int ctrlc_allowed;
+
+void ctrlc_handled(void)
+{
+ ctrlc_abort = 0;
+}
+
/* test if ctrl-c was pressed */
-int ctrlc (void)
+int ctrlc(void)
{
+ int ret = 0;
+
+ if (!ctrlc_allowed)
+ return 0;
+
+ if (ctrlc_abort)
+ return 1;
+
poller_call();
+#ifdef ARCH_HAS_CTRLC
+ ret = arch_ctrlc();
+#else
if (tstc() && getchar() == 3)
- return 1;
- return 0;
+ ret = 1;
+#endif
+
+ if (ret)
+ ctrlc_abort = 1;
+
+ return ret;
}
EXPORT_SYMBOL(ctrlc);
-#endif /* ARCH_HAS_CTRC */
+
+static int console_ctrlc_init(void)
+{
+ globalvar_add_simple_bool("console.ctrlc_allowed", &ctrlc_allowed);
+ return 0;
+}
+device_initcall(console_ctrlc_init);
+
+void console_ctrlc_allow(void)
+{
+ ctrlc_allowed = 1;
+}
+
+void console_ctrlc_forbid(void)
+{
+ ctrlc_allowed = 0;
+}
+
+BAREBOX_MAGICVAR_NAMED(global_console_ctrlc_allowed, global.console.ctrlc_allowed,
+ "If true, scripts can be aborted with ctrl-c");
BAREBOX_MAGICVAR_NAMED(global_linux_bootargs_console, global.linux.bootargs.console,
"console= argument for Linux from the stdout-path property in /chosen node");
diff --git a/common/console_countdown.c b/common/console_countdown.c
index 36da1ce577..8d09894c30 100644
--- a/common/console_countdown.c
+++ b/common/console_countdown.c
@@ -30,7 +30,22 @@ void console_countdown_abort(void)
console_countdown_timeout_abort = true;
}
-int console_countdown(int timeout_s, unsigned flags, char *out_key)
+static int key_in_list(char key, const char *keys)
+{
+ if (!keys)
+ return false;
+
+ while (*keys) {
+ if (key == *keys)
+ return true;
+ keys++;
+ }
+
+ return false;
+}
+
+int console_countdown(int timeout_s, unsigned flags, const char *keys,
+ char *out_key)
{
uint64_t start, second;
int countdown, ret = -EINTR;
@@ -48,6 +63,8 @@ int console_countdown(int timeout_s, unsigned flags, char *out_key)
if (tstc()) {
key = getchar();
if (key >= 0) {
+ if (key_in_list(key, keys))
+ goto out;
if (flags & CONSOLE_COUNTDOWN_ANYKEY)
goto out;
if (flags & CONSOLE_COUNTDOWN_RETURN && key == '\n')
diff --git a/common/hush.c b/common/hush.c
index d2f9cc70f5..dab9b04081 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1734,7 +1734,7 @@ static int parse_stream_outer(struct p_context *ctx, struct in_str *inp, int fla
return 1;
}
b_free(&temp);
- } while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
+ } while (!ctrlc() && rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
return code;
}
@@ -1932,6 +1932,7 @@ int run_shell(void)
login();
do {
+ ctrlc_handled();
setup_file_in_str(&input);
rcode = parse_stream_outer(&ctx, &input, FLAG_PARSE_SEMICOLON);
if (rcode < -1) {
diff --git a/common/parser.c b/common/parser.c
index 397d268da1..fb9ef42e7f 100644
--- a/common/parser.c
+++ b/common/parser.c
@@ -283,6 +283,7 @@ int run_shell(void)
/* invalid command or not repeatable, forget it */
lastcommand[0] = 0;
}
+ ctrlc_handled();
}
}
return 0;
diff --git a/common/startup.c b/common/startup.c
index 28edee4fce..9fac0eabbd 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -42,6 +42,9 @@
#include <asm/sections.h>
#include <uncompress.h>
#include <globalvar.h>
+#include <console_countdown.h>
+#include <environment.h>
+#include <linux/ctype.h>
extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
__barebox_initcalls_end[];
@@ -143,16 +146,172 @@ static int load_environment(void)
environment_initcall(load_environment);
#endif
+static int global_autoboot_abort_key;
+static const char * const global_autoboot_abort_keys[] = {
+ "any",
+ "ctrl-c",
+};
+static int global_autoboot_timeout = 3;
+static char *global_boot_default;
+static char *global_editcmd;
+static char *global_linux_bootargs_base;
+static char *global_linux_bootargs_console;
+static char *global_linux_bootargs_dyn_ip;
+static char *global_linux_bootargs_dyn_root;
+static char *global_user;
+
+static bool test_abort(void)
+{
+ bool do_abort = false;
+ int c, ret;
+ char key;
+
+ while (tstc()) {
+ c = getchar();
+ if (tolower(c) == 'q' || c == 3)
+ do_abort = true;
+ }
+
+ if (!do_abort)
+ return false;
+
+ printf("Abort init sequence? (y/n)\n"
+ "Will continue with init sequence in:");
+
+ ret = console_countdown(5, CONSOLE_COUNTDOWN_EXTERN, "yYnN", &key);
+ if (!ret)
+ return false;
+
+ if (tolower(key) == 'y')
+ return true;
+
+ return false;
+}
+
+static int run_init(void)
+{
+ DIR *dir;
+ struct dirent *d;
+ const char *initfile = "/env/bin/init";
+ const char *initdir = "/env/init";
+ const char *menufile = "/env/menu/mainmenu";
+ struct stat s;
+ unsigned flags = CONSOLE_COUNTDOWN_EXTERN;
+ unsigned char outkey;
+ int ret;
+ bool menu_exists;
+ bool env_bin_init_exists;
+ char *abortkeys = NULL;
+
+ setenv("PATH", "/env/bin");
+
+ /* Run legacy /env/bin/init if it exists */
+ env_bin_init_exists = stat(initfile, &s) == 0;
+ if (env_bin_init_exists) {
+ pr_info("running %s...\n", initfile);
+ run_command(initfile);
+ return 0;
+ }
+
+ global_editcmd = xstrdup("sedit");
+ global_user = xstrdup("none");
+ globalvar_add_simple_string("user", &global_user);
+ global_boot_default = xstrdup("net");
+
+ globalvar_add_simple_enum("autoboot_abort_key",
+ &global_autoboot_abort_key,
+ global_autoboot_abort_keys,
+ ARRAY_SIZE(global_autoboot_abort_keys));
+ globalvar_add_simple_int("autoboot_timeout",
+ &global_autoboot_timeout, "%u");
+ globalvar_add_simple_string("boot.default", &global_boot_default);
+ globalvar_add_simple_string("editcmd", &global_editcmd);
+ globalvar_add_simple_string("linux.bootargs.base",
+ &global_linux_bootargs_base);
+ globalvar_add_simple_string("linux.bootargs.console",
+ &global_linux_bootargs_console);
+ globalvar_add_simple_string("linux.bootargs.dyn.ip",
+ &global_linux_bootargs_dyn_ip);
+ globalvar_add_simple_string("linux.bootargs.dyn.root",
+ &global_linux_bootargs_dyn_root);
+
+ /* Unblank console cursor */
+ printf("\e[?25h");
+
+ if (test_abort()) {
+ pr_info("Init sequence aborted\n");
+ return -EINTR;
+ }
+
+ /* Run scripts in /env/init/ */
+ dir = opendir(initdir);
+ if (dir) {
+ char *scr;
+
+ while ((d = readdir(dir))) {
+ if (*d->d_name == '.')
+ continue;
+
+ pr_debug("Executing '%s/%s'...\n", initdir, d->d_name);
+ scr = basprintf("source %s/%s", initdir, d->d_name);
+ run_command(scr);
+ free(scr);
+ }
+
+ closedir(dir);
+ }
+
+ menu_exists = stat(menufile, &s) == 0;
+
+ if (menu_exists) {
+ printf("\nHit m for menu or %s to stop autoboot: ",
+ global_autoboot_abort_keys[global_autoboot_abort_key]);
+ abortkeys = "m";
+ } else {
+ printf("\nHit %s to stop autoboot: ",
+ global_autoboot_abort_keys[global_autoboot_abort_key]);
+ }
+
+ switch (global_autoboot_abort_key) {
+ case 0:
+ flags |= CONSOLE_COUNTDOWN_ANYKEY;
+ break;
+ case 1:
+ flags |= CONSOLE_COUNTDOWN_CTRLC;
+ break;
+ default:
+ break;
+ }
+
+ ret = console_countdown(global_autoboot_timeout, flags, abortkeys,
+ &outkey);
+
+ if (ret == 0)
+ run_command("boot");
+
+ console_ctrlc_allow();
+
+ if (menu_exists) {
+ if (outkey == 'm')
+ run_command(menufile);
+
+ printf("Enter 'exit' to get back to the menu\n");
+ run_shell();
+ run_command(menufile);
+ }
+
+ return 0;
+}
+
int (*barebox_main)(void);
void __noreturn start_barebox(void)
{
initcall_t *initcall;
int result;
- struct stat s;
- if (!IS_ENABLED(CONFIG_SHELL_NONE))
- barebox_main = run_shell;
+ if (!IS_ENABLED(CONFIG_SHELL_NONE) && IS_ENABLED(CONFIG_COMMAND_SUPPORT))
+ barebox_main = run_init;
for (initcall = __barebox_initcalls_start;
initcall < __barebox_initcalls_end; initcall++) {
@@ -165,25 +324,16 @@ void __noreturn start_barebox(void)
pr_debug("initcalls done\n");
- if (IS_ENABLED(CONFIG_COMMAND_SUPPORT)) {
- pr_info("running /env/bin/init...\n");
-
- if (!stat("/env/bin/init", &s))
- run_command("source /env/bin/init");
- else
- pr_err("/env/bin/init not found\n");
- }
+ if (barebox_main)
+ barebox_main();
- if (!barebox_main) {
- pr_err("No main function! aborting.\n");
+ if (IS_ENABLED(CONFIG_SHELL_NONE)) {
+ pr_err("Nothing left to do\n");
hang();
+ } else {
+ while (1)
+ run_shell();
}
-
- /* main_loop() can return to retry autoboot, if so just run it again. */
- for (;;)
- barebox_main();
-
- /* NOTREACHED - no way out of command loop except booting */
}
void __noreturn hang (void)
diff --git a/defaultenv/defaultenv-2-base/bin/init b/defaultenv/defaultenv-2-base/bin/init
deleted file mode 100644
index 8d02e3d3ab..0000000000
--- a/defaultenv/defaultenv-2-base/bin/init
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-
-export PATH=/env/bin
-
-global hostname
-global user
-global autoboot_timeout
-global autoboot_abort_key
-global boot.default
-global linux.bootargs.base
-global linux.bootargs.console
-#linux.bootargs.dyn.* will be cleared at the beginning of boot
-global linux.bootargs.dyn.ip
-global linux.bootargs.dyn.root
-global editcmd
-
-[ -z "${global.hostname}" ] && global.hostname=generic
-[ -z "${global.user}" ] && global.user=none
-magicvar -a global.user "username (used in network filenames)"
-[ -z "${global.autoboot_timeout}" ] && global.autoboot_timeout=3
-magicvar -a global.autoboot_timeout "timeout in seconds before automatic booting"
-[ -z "${global.autoboot_abort_key}" ] && global.autoboot_abort_key=any
-magicvar -a global.autoboot_abort_key "key to abort automatic booting (valid options: any, ctrl-c)"
-[ -z "${global.boot.default}" ] && global.boot.default=net
-[ -z "${global.editcmd}" ] && global.editcmd=sedit
-
-[ -e /env/config-board ] && /env/config-board
-/env/config
-
-# allow to stop the boot before execute the /env/init/*
-# but without waiting
-timeout -s -a -v key 0
-autoboot="$?"
-
-echo -e -n "\e[?25h"
-if [ "${key}" = "q" ]; then
- exit
-fi
-
-for i in /env/init/*; do
- . $i
-done
-
-if [ "${global.autoboot_abort_key}" = "ctrl-c" ]; then
- abort_string="ctrl-c"
- abort_args="-c"
-else
- abort_string="any key"
- abort_args="-a"
-fi
-
-if [ -e /env/menu ]; then
- echo -e -n "\nHit m for menu or $abort_string to stop autoboot: "
-else
- echo -e -n "\nHit $abort_string to stop autoboot: "
-fi
-
-if [ "$autoboot" = 0 ]; then
- timeout $abort_args $global.autoboot_timeout -v key
- autoboot="$?"
-fi
-
-if [ "${key}" = "q" ]; then
- exit
-fi
-
-if [ "$autoboot" = 0 ]; then
- boot
-fi
-
-if [ -e /env/menu ]; then
- if [ "${key}" != "m" ]; then
- echo -e "\ntype exit to get to the menu"
- sh
- fi
- /env/menu/mainmenu
-fi
diff --git a/include/common.h b/include/common.h
index 11d26cb3db..723b9c706c 100644
--- a/include/common.h
+++ b/include/common.h
@@ -68,7 +68,9 @@ int readline (const char *prompt, char *buf, int len);
long get_ram_size (volatile long *, long);
/* common/console.c */
-int ctrlc (void);
+int ctrlc(void);
+int arch_ctrlc(void);
+void ctrlc_handled(void);
#ifdef ARCH_HAS_STACK_DUMP
void dump_stack(void);
diff --git a/include/console.h b/include/console.h
index 673921331d..4062e5abf6 100644
--- a/include/console.h
+++ b/include/console.h
@@ -207,4 +207,7 @@ static inline void pbl_set_putc(void (*putcf)(void *ctx, int c), void *ctx) {}
bool console_allow_color(void);
+void console_ctrlc_allow(void);
+void console_ctrlc_forbid(void);
+
#endif
diff --git a/include/console_countdown.h b/include/console_countdown.h
index c6c2d5c00e..88cadf11ec 100644
--- a/include/console_countdown.h
+++ b/include/console_countdown.h
@@ -7,7 +7,7 @@
#define CONSOLE_COUNTDOWN_CTRLC (1 << 4)
#define CONSOLE_COUNTDOWN_EXTERN (1 << 5)
-int console_countdown(int timeout_s, unsigned flags, char *out_key);
+int console_countdown(int timeout_s, unsigned flags, const char *keys, char *out_key);
void console_countdown_abort(void);
#endif /* __CONSOLE_COUNTDOWN_H */