diff options
Diffstat (limited to 'common/startup.c')
-rw-r--r-- | common/startup.c | 209 |
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"); |