From: Roland Hieber <rhi@pengutronix.de>
To: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Barebox List <barebox@lists.infradead.org>
Subject: Re: [PATCH 4/4] defaultenv: Convert init script to C
Date: Fri, 26 Apr 2019 14:37:05 +0200 [thread overview]
Message-ID: <20190426123705.payrtca5k5a3ilsj@pengutronix.de> (raw)
In-Reply-To: <20190424102650.9257-4-s.hauer@pengutronix.de>
Hi Sascha,
small note: one might want to interrupt long-running processes during
the init sequence, e.g. if an init script contains a "dhcp" call or does
some NFS mount, but the board is currently not connected to the network.
Now it is no longer possible to interrupt such processes, even when
global.autoboot_abort_key is set to anything else than "ctrl-c". Was
this use case considered?
- Roland
On Wed, Apr 24, 2019 at 12:26:50PM +0200, Sascha Hauer wrote:
> It's hard to get more complicated things right in hush. This commit
> converts the /env/bin/init script to C code. With this we get a better
> error handling and better control what is being done.
>
> If /env/bin/init exists in the environment then it is still executed
> instead of the corresponding C code.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> common/startup.c | 188 +++++++++++++++++++++++---
> defaultenv/defaultenv-2-base/bin/init | 79 -----------
> 2 files changed, 169 insertions(+), 98 deletions(-)
> delete mode 100644 defaultenv/defaultenv-2-base/bin/init
>
> 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 a5d3a984f7..0000000000
> --- a/defaultenv/defaultenv-2-base/bin/init
> +++ /dev/null
> @@ -1,79 +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
> -
> -global.console.ctrlc_allowed=true
> -
> -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
> --
> 2.20.1
>
>
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
>
--
Roland Hieber | r.hieber@pengutronix.de |
Pengutronix e.K. | https://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim | Phone: +49-5121-206917-5086 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2019-04-26 12:37 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-24 10:26 [PATCH 1/4] Shell: Handle aborting loops better Sascha Hauer
2019-04-24 10:26 ` [PATCH 2/4] console: forbid ctrlc during startup Sascha Hauer
2019-04-24 10:26 ` [PATCH 3/4] console_countdown: Add pattern list Sascha Hauer
2019-04-24 10:26 ` [PATCH 4/4] defaultenv: Convert init script to C Sascha Hauer
2019-04-26 12:37 ` Roland Hieber [this message]
2019-04-29 6:57 ` Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190426123705.payrtca5k5a3ilsj@pengutronix.de \
--to=rhi@pengutronix.de \
--cc=barebox@lists.infradead.org \
--cc=s.hauer@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox