summaryrefslogtreecommitdiffstats
path: root/common/startup.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/startup.c')
-rw-r--r--common/startup.c209
1 files changed, 97 insertions, 112 deletions
diff --git a/common/startup.c b/common/startup.c
index 511675ed55..47b70a7756 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright 2002-2006
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
@@ -5,17 +6,6 @@
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
- *
- * 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.
- *
*/
#ifdef CONFIG_DEBUG_INITCALLS
@@ -34,15 +24,22 @@
#include <debug_ll.h>
#include <fs.h>
#include <errno.h>
+#include <slice.h>
#include <linux/stat.h>
#include <envfs.h>
#include <magicvar.h>
+#include <linux/reboot-mode.h>
#include <asm/sections.h>
#include <uncompress.h>
#include <globalvar.h>
#include <console_countdown.h>
#include <environment.h>
#include <linux/ctype.h>
+#include <watchdog.h>
+#include <glob.h>
+#include <net.h>
+#include <efi/efi-mode.h>
+#include <bselftest.h>
extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
__barebox_initcalls_end[];
@@ -58,7 +55,7 @@ static int mount_root(void)
mkdir("/tmp", 0);
mount("none", "devfs", "/dev", NULL);
- if (IS_ENABLED(CONFIG_FS_EFIVARFS)) {
+ if (IS_ENABLED(CONFIG_FS_EFIVARFS) && efi_is_payload()) {
mkdir("/efivars", 0);
mount("none", "efivarfs", "/efivars", NULL);
}
@@ -73,70 +70,6 @@ static int mount_root(void)
fs_initcall(mount_root);
#endif
-#ifdef CONFIG_ENV_HANDLING
-static bool region_overlap(loff_t starta, loff_t lena,
- loff_t startb, loff_t lenb)
-{
- if (starta + lena <= startb)
- return 0;
- if (startb + lenb <= starta)
- return 0;
- return 1;
-}
-
-static int check_overlap(const char *path)
-{
- struct cdev *cenv, *cdisk, *cpart;
- const char *name;
-
- name = devpath_to_name(path);
-
- if (name == path)
- /*
- * no /dev/ in front, so *path is some file. No need to
- * check further.
- */
- return 0;
-
- cenv = cdev_by_name(name);
- if (!cenv)
- return -EINVAL;
-
- if (cenv->mtd)
- return 0;
-
- cdisk = cenv->master;
-
- if (!cdisk)
- return 0;
-
- list_for_each_entry(cpart, &cdisk->partitions, partition_entry) {
- if (cpart == cenv)
- continue;
-
- if (region_overlap(cpart->offset, cpart->size,
- cenv->offset, cenv->size))
- goto conflict;
- }
-
- return 0;
-
-conflict:
- pr_err("Environment partition (0x%08llx-0x%08llx) "
- "overlaps with partition %s (0x%08llx-0x%08llx), not using it\n",
- cenv->offset, cenv->offset + cenv->size - 1,
- cpart->name,
- cpart->offset, cpart->offset + cpart->size - 1);
-
- return -EINVAL;
-}
-#else
-static int check_overlap(const char *path)
-{
- return 0;
-}
-#endif
-
static int load_environment(void)
{
const char *default_environment_path;
@@ -148,14 +81,10 @@ static int load_environment(void)
defaultenv_load("/env", 0);
if (IS_ENABLED(CONFIG_ENV_HANDLING)) {
- ret = check_overlap(default_environment_path);
- if (ret)
- default_environment_path_set(NULL);
- else
- envfs_load(default_environment_path, "/env", 0);
+ envfs_load(default_environment_path, "/env", 0);
} else {
if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT))
- pr_notice("No support for persistent environment. Using default environment");
+ pr_notice("No support for persistent environment. Using default environment\n");
}
nvvar_load();
@@ -235,7 +164,7 @@ void set_autoboot_state(enum autoboot_state autoboot)
*/
enum autoboot_state do_autoboot_countdown(void)
{
- enum autoboot_state autoboot_state;
+ static enum autoboot_state autoboot_state = AUTOBOOT_UNKNOWN;
unsigned flags = CONSOLE_COUNTDOWN_EXTERN;
int ret;
struct stat s;
@@ -243,6 +172,15 @@ enum autoboot_state do_autoboot_countdown(void)
char *abortkeys = NULL;
unsigned char outkey;
+ if (autoboot_state != AUTOBOOT_UNKNOWN)
+ return autoboot_state;
+
+ if (!console_get_first_active() &&
+ global_autoboot_state != AUTOBOOT_ABORT) {
+ printf("\nNon-interactive console, booting system\n");
+ return autoboot_state = AUTOBOOT_BOOT;
+ }
+
if (global_autoboot_state != AUTOBOOT_COUNTDOWN)
return global_autoboot_state;
@@ -268,8 +206,10 @@ enum autoboot_state do_autoboot_countdown(void)
break;
}
+ command_slice_release();
ret = console_countdown(global_autoboot_timeout, flags, abortkeys,
&outkey);
+ command_slice_acquire();
if (ret == 0)
autoboot_state = AUTOBOOT_BOOT;
@@ -281,19 +221,8 @@ enum autoboot_state do_autoboot_countdown(void)
return autoboot_state;
}
-static int run_init(void)
+static int register_autoboot_vars(void)
{
- DIR *dir;
- struct dirent *d;
- const char *initdir = "/env/init";
- bool env_bin_init_exists;
- enum autoboot_state autoboot;
- struct stat s;
-
- /*
- * Register autoboot variables here as they might be altered by
- * init scripts.
- */
globalvar_add_simple_enum("autoboot_abort_key",
&global_autoboot_abort_key,
global_autoboot_abort_keys,
@@ -305,7 +234,21 @@ static int run_init(void)
global_autoboot_states,
ARRAY_SIZE(global_autoboot_states));
+ return 0;
+}
+postcore_initcall(register_autoboot_vars);
+
+static int run_init(void)
+{
+ const char *bmode;
+ bool env_bin_init_exists;
+ enum autoboot_state autoboot;
+ struct stat s;
+ glob_t g;
+ int i, ret;
+
setenv("PATH", "/env/bin");
+ export("PATH");
/* Run legacy /env/bin/init if it exists */
env_bin_init_exists = stat(INITFILE, &s) == 0;
@@ -324,21 +267,40 @@ static int run_init(void)
}
/* Run scripts in /env/init/ */
- dir = opendir(initdir);
- if (dir) {
- char *scr;
+ ret = glob("/env/init/*", 0, NULL, &g);
+ if (!ret) {
+ for (i = 0; i < g.gl_pathc; i++) {
+ const char *path = g.gl_pathv[i];
+ char *scr;
+
+ ret = stat(path, &s);
+ if (ret)
+ continue;
- while ((d = readdir(dir))) {
- if (*d->d_name == '.')
+ if (!S_ISREG(s.st_mode))
continue;
- pr_debug("Executing '%s/%s'...\n", initdir, d->d_name);
- scr = basprintf("source %s/%s", initdir, d->d_name);
+ pr_debug("Executing '%s'...\n", path);
+ scr = basprintf("source %s", path);
run_command(scr);
free(scr);
}
- closedir(dir);
+ globfree(&g);
+ }
+
+ /* source matching script in /env/bmode/ */
+ bmode = reboot_mode_get();
+ if (bmode) {
+ char *scr, *path;
+
+ scr = xasprintf("source /env/bmode/%s", bmode);
+ path = &scr[strlen("source ")];
+ if (stat(path, &s) == 0) {
+ pr_info("Invoking '%s'...\n", path);
+ run_command(scr);
+ }
+ free(scr);
}
autoboot = do_autoboot_countdown();
@@ -348,15 +310,34 @@ static int run_init(void)
if (autoboot == AUTOBOOT_BOOT)
run_command("boot");
+ if (IS_ENABLED(CONFIG_NET))
+ eth_open_all();
+
if (autoboot == AUTOBOOT_MENU)
run_command(MENUFILE);
+ if (autoboot == AUTOBOOT_ABORT && autoboot == global_autoboot_state)
+ watchdog_inhibit_all();
+
run_shell();
run_command(MENUFILE);
return 0;
}
+typedef void (*ctor_fn_t)(void);
+
+/* Call all constructor functions linked into the kernel. */
+static void do_ctors(void)
+{
+#ifdef CONFIG_CONSTRUCTORS
+ ctor_fn_t *fn = (ctor_fn_t *) __ctors_start;
+
+ for (; fn < (ctor_fn_t *) __ctors_end; fn++)
+ (*fn)();
+#endif
+}
+
int (*barebox_main)(void);
void __noreturn start_barebox(void)
@@ -367,6 +348,8 @@ void __noreturn start_barebox(void)
if (!IS_ENABLED(CONFIG_SHELL_NONE) && IS_ENABLED(CONFIG_COMMAND_SUPPORT))
barebox_main = run_init;
+ do_ctors();
+
for (initcall = __barebox_initcalls_start;
initcall < __barebox_initcalls_end; initcall++) {
pr_debug("initcall-> %pS\n", *initcall);
@@ -378,6 +361,9 @@ void __noreturn start_barebox(void)
pr_debug("initcalls done\n");
+ if (IS_ENABLED(CONFIG_SELFTEST_AUTORUN))
+ selftests_run();
+
if (barebox_main)
barebox_main();
@@ -409,14 +395,13 @@ void shutdown_barebox(void)
pr_debug("exitcall-> %pS\n", *exitcall);
(*exitcall)();
}
+
+ console_flush();
}
-BAREBOX_MAGICVAR_NAMED(autoboot_state,
- global.autoboot,
- "Autoboot state. Possible values: countdown (default), abort, menu, boot");
-BAREBOX_MAGICVAR_NAMED(global_autoboot_abort_key,
- global.autoboot_abort_key,
- "Which key allows to interrupt autoboot. Possible values: any, ctrl-c");
-BAREBOX_MAGICVAR_NAMED(global_autoboot_timeout,
- global.autoboot_timeout,
- "Timeout before autoboot starts in seconds");
+BAREBOX_MAGICVAR(global.autoboot,
+ "Autoboot state. Possible values: countdown (default), abort, menu, boot");
+BAREBOX_MAGICVAR(global.autoboot_abort_key,
+ "Which key allows to interrupt autoboot. Possible values: any, ctrl-c");
+BAREBOX_MAGICVAR(global.autoboot_timeout,
+ "Timeout before autoboot starts in seconds");