boot: Move code to common/
Normally code in commands/ shall only do the option parsing whereas the functionality shall be in common/ to make the code usable from C aswell. Do this in the boot code aswell, move it to common/boot.c and add the function prototypes to include/boot.h Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
ed71dfbbc5
commit
89c8ac578f
|
@ -294,6 +294,7 @@ config CMD_BOOT_ORDER
|
|||
config CMD_BOOT
|
||||
tristate
|
||||
depends on BOOTM
|
||||
select BOOT
|
||||
prompt "boot"
|
||||
help
|
||||
Select this for booting based on scripts. Unlike the bootm command which
|
||||
|
|
334
commands/boot.c
334
commands/boot.c
|
@ -11,339 +11,21 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <environment.h>
|
||||
#include <globalvar.h>
|
||||
#include <magicvar.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <readkey.h>
|
||||
#include <common.h>
|
||||
#include <getopt.h>
|
||||
#include <blspec.h>
|
||||
#include <libgen.h>
|
||||
#include <malloc.h>
|
||||
#include <clock.h>
|
||||
#include <bootm.h>
|
||||
#include <glob.h>
|
||||
#include <init.h>
|
||||
#include <menu.h>
|
||||
#include <fs.h>
|
||||
#include <boot.h>
|
||||
#include <complete.h>
|
||||
|
||||
#include <linux/stat.h>
|
||||
|
||||
static int verbose;
|
||||
static int dryrun;
|
||||
static int timeout;
|
||||
|
||||
int bootentries_add_entry(struct bootentries *entries, struct bootentry *entry)
|
||||
{
|
||||
list_add_tail(&entry->list, &entries->entries);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct bootentries *bootentries_alloc(void)
|
||||
{
|
||||
struct bootentries *bootentries;
|
||||
|
||||
bootentries = xzalloc(sizeof(*bootentries));
|
||||
INIT_LIST_HEAD(&bootentries->entries);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MENU)) {
|
||||
bootentries->menu = menu_alloc();
|
||||
bootentries->menu->display = basprintf("boot");
|
||||
}
|
||||
|
||||
return bootentries;
|
||||
}
|
||||
|
||||
static void bootentries_free(struct bootentries *bootentries)
|
||||
{
|
||||
struct bootentry *be, *tmp;
|
||||
|
||||
list_for_each_entry_safe(be, tmp, &bootentries->entries, list) {
|
||||
list_del(&be->list);
|
||||
free(be->title);
|
||||
free(be->description);
|
||||
free(be->me.display);
|
||||
be->release(be);
|
||||
}
|
||||
|
||||
if (bootentries->menu)
|
||||
free(bootentries->menu->display);
|
||||
free(bootentries->menu);
|
||||
free(bootentries);
|
||||
}
|
||||
|
||||
struct bootentry_script {
|
||||
struct bootentry entry;
|
||||
char *scriptpath;
|
||||
};
|
||||
|
||||
/*
|
||||
* Start a single boot script. 'path' is a full path to a boot script.
|
||||
*/
|
||||
static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
|
||||
{
|
||||
struct bootentry_script *bs = container_of(entry, struct bootentry_script, entry);
|
||||
int ret;
|
||||
|
||||
struct bootm_data data = {};
|
||||
|
||||
if (dryrun) {
|
||||
printf("Would run %s\n", bs->scriptpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
globalvar_set_match("linux.bootargs.dyn.", "");
|
||||
|
||||
ret = run_command(bs->scriptpath);
|
||||
if (ret) {
|
||||
printf("Running %s failed\n", bs->scriptpath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bootm_data_init_defaults(&data);
|
||||
|
||||
if (verbose)
|
||||
data.verbose = verbose;
|
||||
if (dryrun)
|
||||
data.dryrun = dryrun;
|
||||
|
||||
ret = bootm_boot(&data);
|
||||
if (ret)
|
||||
pr_err("Booting %s failed: %s\n", basename(bs->scriptpath), strerror(-ret));
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int boot_watchdog_timeout;
|
||||
|
||||
static int init_boot_watchdog_timeout(void)
|
||||
{
|
||||
return globalvar_add_simple_int("boot.watchdog_timeout",
|
||||
&boot_watchdog_timeout, "%u");
|
||||
}
|
||||
late_initcall(init_boot_watchdog_timeout);
|
||||
|
||||
BAREBOX_MAGICVAR_NAMED(global_watchdog_timeout, global.boot.watchdog_timeout,
|
||||
"Watchdog enable timeout in seconds before booting");
|
||||
|
||||
static int boot_entry(struct bootentry *be)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printf("booting %s\n", be->title);
|
||||
|
||||
if (IS_ENABLED(CONFIG_WATCHDOG) && boot_watchdog_timeout) {
|
||||
ret = watchdog_set_timeout(boot_watchdog_timeout);
|
||||
if (ret)
|
||||
pr_warn("Failed to enable watchdog: %s\n", strerror(-ret));
|
||||
}
|
||||
|
||||
ret = be->boot(be, verbose, dryrun);
|
||||
|
||||
if (ret)
|
||||
printf("booting %s failed: %s\n", be->title, strerror(-ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bootsource_action(struct menu *m, struct menu_entry *me)
|
||||
{
|
||||
struct bootentry *be = container_of(me, struct bootentry, me);
|
||||
int ret;
|
||||
|
||||
ret = boot_entry(be);
|
||||
if (ret)
|
||||
printf("Booting failed with: %s\n", strerror(-ret));
|
||||
|
||||
printf("Press any key to continue\n");
|
||||
|
||||
read_key();
|
||||
}
|
||||
|
||||
static void bootscript_entry_release(struct bootentry *entry)
|
||||
{
|
||||
struct bootentry_script *bs = container_of(entry, struct bootentry_script, entry);
|
||||
|
||||
free(bs->scriptpath);
|
||||
free(bs->entry.me.display);
|
||||
free(bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* bootscript_create_entry - create a boot entry from a script name
|
||||
*/
|
||||
static int bootscript_create_entry(struct bootentries *bootentries, const char *name)
|
||||
{
|
||||
struct bootentry_script *bs;
|
||||
enum filetype type;
|
||||
|
||||
type = file_name_detect_type(name);
|
||||
if (type != filetype_sh)
|
||||
return -EINVAL;
|
||||
|
||||
bs = xzalloc(sizeof(*bs));
|
||||
bs->entry.me.type = MENU_ENTRY_NORMAL;
|
||||
bs->entry.release = bootscript_entry_release;
|
||||
bs->entry.boot = bootscript_boot;
|
||||
bs->scriptpath = xstrdup(name);
|
||||
bs->entry.title = xstrdup(basename(bs->scriptpath));
|
||||
bs->entry.description = basprintf("script: %s", name);
|
||||
bootentries_add_entry(bootentries, &bs->entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* bootscript_scan_path - create boot entries from a path
|
||||
*
|
||||
* path can either be a full path to a bootscript or a full path to a diretory
|
||||
* containing bootscripts.
|
||||
*/
|
||||
static int bootscript_scan_path(struct bootentries *bootentries, const char *path)
|
||||
{
|
||||
struct stat s;
|
||||
char *files;
|
||||
int ret, i;
|
||||
int found = 0;
|
||||
glob_t globb;
|
||||
|
||||
ret = stat(path, &s);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!S_ISDIR(s.st_mode)) {
|
||||
ret = bootscript_create_entry(bootentries, path);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
files = basprintf("%s/*", path);
|
||||
|
||||
glob(files, 0, NULL, &globb);
|
||||
|
||||
for (i = 0; i < globb.gl_pathc; i++) {
|
||||
char *bootscript_path = globb.gl_pathv[i];
|
||||
|
||||
if (*basename(bootscript_path) == '.')
|
||||
continue;
|
||||
|
||||
bootscript_create_entry(bootentries, bootscript_path);
|
||||
found++;
|
||||
}
|
||||
|
||||
globfree(&globb);
|
||||
free(files);
|
||||
|
||||
ret = found;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* bootentry_parse_one - create boot entries from a name
|
||||
*
|
||||
* name can be:
|
||||
* - a name of a boot script under /env/boot
|
||||
* - a full path of a boot script
|
||||
* - a device name
|
||||
* - a cdev name
|
||||
* - a full path of a directory containing bootloader spec entries
|
||||
* - a full path of a directory containing bootscripts
|
||||
*
|
||||
* Returns the number of entries found or a negative error code.
|
||||
*/
|
||||
static int bootentry_parse_one(struct bootentries *bootentries, const char *name)
|
||||
{
|
||||
int found = 0, ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLSPEC)) {
|
||||
ret = blspec_scan_devicename(bootentries, name);
|
||||
if (ret > 0)
|
||||
found += ret;
|
||||
|
||||
if (*name == '/') {
|
||||
ret = blspec_scan_directory(bootentries, name);
|
||||
if (ret > 0)
|
||||
found += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
char *path;
|
||||
|
||||
if (*name != '/')
|
||||
path = basprintf("/env/boot/%s", name);
|
||||
else
|
||||
path = xstrdup(name);
|
||||
|
||||
ret = bootscript_scan_path(bootentries, path);
|
||||
if (ret > 0)
|
||||
found += ret;
|
||||
|
||||
free(path);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* bootsources_menu - show a menu from an array of names
|
||||
*/
|
||||
static void bootsources_menu(struct bootentries *bootentries)
|
||||
{
|
||||
struct bootentry *entry;
|
||||
struct menu_entry *back_entry;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_MENU)) {
|
||||
printf("no menu support available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bootentries_for_each_entry(bootentries, entry) {
|
||||
if (!entry->me.display)
|
||||
entry->me.display = xstrdup(entry->title);
|
||||
entry->me.action = bootsource_action;
|
||||
menu_add_entry(bootentries->menu, &entry->me);
|
||||
}
|
||||
|
||||
back_entry = xzalloc(sizeof(*back_entry));
|
||||
back_entry->display = "back";
|
||||
back_entry->type = MENU_ENTRY_NORMAL;
|
||||
back_entry->non_re_ent = 1;
|
||||
menu_add_entry(bootentries->menu, back_entry);
|
||||
|
||||
if (timeout >= 0)
|
||||
bootentries->menu->auto_select = timeout;
|
||||
|
||||
menu_show(bootentries->menu);
|
||||
|
||||
free(back_entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* bootsources_list - list boot entries from an array of names
|
||||
*/
|
||||
static void bootsources_list(struct bootentries *bootentries)
|
||||
{
|
||||
struct bootentry *entry;
|
||||
|
||||
printf("%-20s\n", "title");
|
||||
printf("%-20s\n", "------");
|
||||
|
||||
bootentries_for_each_entry(bootentries, entry)
|
||||
printf("%-20s %s\n", entry->title, entry->description);
|
||||
}
|
||||
|
||||
static int do_boot(int argc, char *argv[])
|
||||
{
|
||||
char *freep = NULL;
|
||||
int opt, ret = 0, do_list = 0, do_menu = 0;
|
||||
int i;
|
||||
int i, dryrun = 0, verbose = 0, timeout = -1;
|
||||
struct bootentries *entries;
|
||||
struct bootentry *entry;
|
||||
|
||||
|
@ -369,7 +51,7 @@ static int do_boot(int argc, char *argv[])
|
|||
timeout = simple_strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'w':
|
||||
boot_watchdog_timeout = simple_strtoul(optarg, NULL, 0);
|
||||
boot_set_watchdog_timeout(simple_strtoul(optarg, NULL, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -378,7 +60,7 @@ static int do_boot(int argc, char *argv[])
|
|||
|
||||
if (optind < argc) {
|
||||
for (i = optind; i < argc; i++)
|
||||
bootentry_parse_one(entries, argv[i]);
|
||||
bootentry_create_from_name(entries, argv[i]);
|
||||
} else {
|
||||
const char *def;
|
||||
char *sep, *name;
|
||||
|
@ -390,7 +72,7 @@ static int do_boot(int argc, char *argv[])
|
|||
sep = freep = xstrdup(def);
|
||||
|
||||
while ((name = strsep(&sep, " ")) != NULL)
|
||||
bootentry_parse_one(entries, name);
|
||||
bootentry_create_from_name(entries, name);
|
||||
|
||||
free(freep);
|
||||
}
|
||||
|
@ -401,12 +83,12 @@ static int do_boot(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (do_menu) {
|
||||
bootsources_menu(entries);
|
||||
bootsources_menu(entries, timeout);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bootentries_for_each_entry(entries, entry) {
|
||||
ret = boot_entry(entry);
|
||||
ret = boot_entry(entry, verbose, dryrun);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
|
@ -450,5 +132,3 @@ BAREBOX_CMD_START(boot)
|
|||
BAREBOX_CMD_GROUP(CMD_GRP_BOOT)
|
||||
BAREBOX_CMD_HELP(cmd_boot_help)
|
||||
BAREBOX_CMD_END
|
||||
|
||||
BAREBOX_MAGICVAR_NAMED(global_boot_default, global.boot.default, "default boot order");
|
||||
|
|
|
@ -110,6 +110,9 @@ config UBIFORMAT
|
|||
depends on MTD_UBI
|
||||
default y
|
||||
|
||||
config BOOT
|
||||
bool
|
||||
|
||||
menu "General Settings"
|
||||
|
||||
config LOCALVERSION
|
||||
|
|
|
@ -58,6 +58,7 @@ obj-$(CONFIG_FIRMWARE) += firmware.o
|
|||
obj-$(CONFIG_UBIFORMAT) += ubiformat.o
|
||||
obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o
|
||||
obj-$(CONFIG_CONSOLE_RATP) += ratp.o
|
||||
obj-$(CONFIG_BOOT) += boot.o
|
||||
|
||||
quiet_cmd_pwd_h = PWDH $@
|
||||
ifdef CONFIG_PASSWORD
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* 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; version 2.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <environment.h>
|
||||
#include <globalvar.h>
|
||||
#include <magicvar.h>
|
||||
#include <watchdog.h>
|
||||
#include <command.h>
|
||||
#include <readkey.h>
|
||||
#include <common.h>
|
||||
#include <blspec.h>
|
||||
#include <libgen.h>
|
||||
#include <malloc.h>
|
||||
#include <bootm.h>
|
||||
#include <glob.h>
|
||||
#include <init.h>
|
||||
#include <menu.h>
|
||||
#include <fs.h>
|
||||
|
||||
#include <linux/stat.h>
|
||||
|
||||
int bootentries_add_entry(struct bootentries *entries, struct bootentry *entry)
|
||||
{
|
||||
list_add_tail(&entry->list, &entries->entries);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bootentries *bootentries_alloc(void)
|
||||
{
|
||||
struct bootentries *bootentries;
|
||||
|
||||
bootentries = xzalloc(sizeof(*bootentries));
|
||||
INIT_LIST_HEAD(&bootentries->entries);
|
||||
|
||||
if (IS_ENABLED(CONFIG_MENU)) {
|
||||
bootentries->menu = menu_alloc();
|
||||
bootentries->menu->display = basprintf("boot");
|
||||
}
|
||||
|
||||
return bootentries;
|
||||
}
|
||||
|
||||
void bootentries_free(struct bootentries *bootentries)
|
||||
{
|
||||
struct bootentry *be, *tmp;
|
||||
|
||||
list_for_each_entry_safe(be, tmp, &bootentries->entries, list) {
|
||||
list_del(&be->list);
|
||||
free(be->title);
|
||||
free(be->description);
|
||||
free(be->me.display);
|
||||
be->release(be);
|
||||
}
|
||||
|
||||
if (bootentries->menu)
|
||||
free(bootentries->menu->display);
|
||||
free(bootentries->menu);
|
||||
free(bootentries);
|
||||
}
|
||||
|
||||
struct bootentry_script {
|
||||
struct bootentry entry;
|
||||
char *scriptpath;
|
||||
};
|
||||
|
||||
/*
|
||||
* Start a single boot script. 'path' is a full path to a boot script.
|
||||
*/
|
||||
static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
|
||||
{
|
||||
struct bootentry_script *bs = container_of(entry, struct bootentry_script, entry);
|
||||
int ret;
|
||||
|
||||
struct bootm_data data = {};
|
||||
|
||||
if (dryrun) {
|
||||
printf("Would run %s\n", bs->scriptpath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
globalvar_set_match("linux.bootargs.dyn.", "");
|
||||
|
||||
ret = run_command(bs->scriptpath);
|
||||
if (ret) {
|
||||
printf("Running %s failed\n", bs->scriptpath);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bootm_data_init_defaults(&data);
|
||||
|
||||
if (verbose)
|
||||
data.verbose = verbose;
|
||||
if (dryrun)
|
||||
data.dryrun = dryrun;
|
||||
|
||||
ret = bootm_boot(&data);
|
||||
if (ret)
|
||||
pr_err("Booting %s failed: %s\n", basename(bs->scriptpath), strerror(-ret));
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int boot_watchdog_timeout;
|
||||
|
||||
void boot_set_watchdog_timeout(unsigned int timeout)
|
||||
{
|
||||
boot_watchdog_timeout = timeout;
|
||||
}
|
||||
|
||||
static int init_boot_watchdog_timeout(void)
|
||||
{
|
||||
return globalvar_add_simple_int("boot.watchdog_timeout",
|
||||
&boot_watchdog_timeout, "%u");
|
||||
}
|
||||
late_initcall(init_boot_watchdog_timeout);
|
||||
|
||||
BAREBOX_MAGICVAR_NAMED(global_watchdog_timeout, global.boot.watchdog_timeout,
|
||||
"Watchdog enable timeout in seconds before booting");
|
||||
|
||||
int boot_entry(struct bootentry *be, int verbose, int dryrun)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printf("booting %s\n", be->title);
|
||||
|
||||
if (IS_ENABLED(CONFIG_WATCHDOG) && boot_watchdog_timeout) {
|
||||
ret = watchdog_set_timeout(boot_watchdog_timeout);
|
||||
if (ret)
|
||||
pr_warn("Failed to enable watchdog: %s\n", strerror(-ret));
|
||||
}
|
||||
|
||||
ret = be->boot(be, verbose, dryrun);
|
||||
|
||||
if (ret)
|
||||
printf("booting %s failed: %s\n", be->title, strerror(-ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bootsource_action(struct menu *m, struct menu_entry *me)
|
||||
{
|
||||
struct bootentry *be = container_of(me, struct bootentry, me);
|
||||
int ret;
|
||||
|
||||
ret = boot_entry(be, 0, 0);
|
||||
if (ret)
|
||||
printf("Booting failed with: %s\n", strerror(-ret));
|
||||
|
||||
printf("Press any key to continue\n");
|
||||
|
||||
read_key();
|
||||
}
|
||||
|
||||
static void bootscript_entry_release(struct bootentry *entry)
|
||||
{
|
||||
struct bootentry_script *bs = container_of(entry, struct bootentry_script, entry);
|
||||
|
||||
free(bs->scriptpath);
|
||||
free(bs->entry.me.display);
|
||||
free(bs);
|
||||
}
|
||||
|
||||
/*
|
||||
* bootscript_create_entry - create a boot entry from a script name
|
||||
*/
|
||||
static int bootscript_create_entry(struct bootentries *bootentries, const char *name)
|
||||
{
|
||||
struct bootentry_script *bs;
|
||||
enum filetype type;
|
||||
|
||||
type = file_name_detect_type(name);
|
||||
if (type != filetype_sh)
|
||||
return -EINVAL;
|
||||
|
||||
bs = xzalloc(sizeof(*bs));
|
||||
bs->entry.me.type = MENU_ENTRY_NORMAL;
|
||||
bs->entry.release = bootscript_entry_release;
|
||||
bs->entry.boot = bootscript_boot;
|
||||
bs->scriptpath = xstrdup(name);
|
||||
bs->entry.title = xstrdup(basename(bs->scriptpath));
|
||||
bs->entry.description = basprintf("script: %s", name);
|
||||
bootentries_add_entry(bootentries, &bs->entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* bootscript_scan_path - create boot entries from a path
|
||||
*
|
||||
* path can either be a full path to a bootscript or a full path to a diretory
|
||||
* containing bootscripts.
|
||||
*/
|
||||
static int bootscript_scan_path(struct bootentries *bootentries, const char *path)
|
||||
{
|
||||
struct stat s;
|
||||
char *files;
|
||||
int ret, i;
|
||||
int found = 0;
|
||||
glob_t globb;
|
||||
|
||||
ret = stat(path, &s);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!S_ISDIR(s.st_mode)) {
|
||||
ret = bootscript_create_entry(bootentries, path);
|
||||
if (ret)
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
files = basprintf("%s/*", path);
|
||||
|
||||
glob(files, 0, NULL, &globb);
|
||||
|
||||
for (i = 0; i < globb.gl_pathc; i++) {
|
||||
char *bootscript_path = globb.gl_pathv[i];
|
||||
|
||||
if (*basename(bootscript_path) == '.')
|
||||
continue;
|
||||
|
||||
bootscript_create_entry(bootentries, bootscript_path);
|
||||
found++;
|
||||
}
|
||||
|
||||
globfree(&globb);
|
||||
free(files);
|
||||
|
||||
ret = found;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* bootentry_create_from_name - create boot entries from a name
|
||||
*
|
||||
* name can be:
|
||||
* - a name of a boot script under /env/boot
|
||||
* - a full path of a boot script
|
||||
* - a device name
|
||||
* - a cdev name
|
||||
* - a full path of a directory containing bootloader spec entries
|
||||
* - a full path of a directory containing bootscripts
|
||||
*
|
||||
* Returns the number of entries found or a negative error code.
|
||||
*/
|
||||
int bootentry_create_from_name(struct bootentries *bootentries,
|
||||
const char *name)
|
||||
{
|
||||
int found = 0, ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLSPEC)) {
|
||||
ret = blspec_scan_devicename(bootentries, name);
|
||||
if (ret > 0)
|
||||
found += ret;
|
||||
|
||||
if (*name == '/') {
|
||||
ret = blspec_scan_directory(bootentries, name);
|
||||
if (ret > 0)
|
||||
found += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
char *path;
|
||||
|
||||
if (*name != '/')
|
||||
path = basprintf("/env/boot/%s", name);
|
||||
else
|
||||
path = xstrdup(name);
|
||||
|
||||
ret = bootscript_scan_path(bootentries, path);
|
||||
if (ret > 0)
|
||||
found += ret;
|
||||
|
||||
free(path);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
* bootsources_menu - show a menu from an array of names
|
||||
*/
|
||||
void bootsources_menu(struct bootentries *bootentries, int timeout)
|
||||
{
|
||||
struct bootentry *entry;
|
||||
struct menu_entry *back_entry;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_MENU)) {
|
||||
printf("no menu support available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bootentries_for_each_entry(bootentries, entry) {
|
||||
if (!entry->me.display)
|
||||
entry->me.display = xstrdup(entry->title);
|
||||
entry->me.action = bootsource_action;
|
||||
menu_add_entry(bootentries->menu, &entry->me);
|
||||
}
|
||||
|
||||
back_entry = xzalloc(sizeof(*back_entry));
|
||||
back_entry->display = "back";
|
||||
back_entry->type = MENU_ENTRY_NORMAL;
|
||||
back_entry->non_re_ent = 1;
|
||||
menu_add_entry(bootentries->menu, back_entry);
|
||||
|
||||
if (timeout >= 0)
|
||||
bootentries->menu->auto_select = timeout;
|
||||
|
||||
menu_show(bootentries->menu);
|
||||
|
||||
free(back_entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* bootsources_list - list boot entries from an array of names
|
||||
*/
|
||||
void bootsources_list(struct bootentries *bootentries)
|
||||
{
|
||||
struct bootentry *entry;
|
||||
|
||||
printf("%-20s\n", "title");
|
||||
printf("%-20s\n", "------");
|
||||
|
||||
bootentries_for_each_entry(bootentries, entry)
|
||||
printf("%-20s %s\n", entry->title, entry->description);
|
||||
}
|
||||
|
||||
BAREBOX_MAGICVAR_NAMED(global_boot_default, global.boot.default, "default boot order");
|
|
@ -39,4 +39,13 @@ int bootentries_add_entry(struct bootentries *entries, struct bootentry *entry);
|
|||
#define bootentries_for_each_entry(bootentries, entry) \
|
||||
list_for_each_entry(entry, &bootentries->entries, list)
|
||||
|
||||
void boot_set_watchdog_timeout(unsigned int timeout);
|
||||
struct bootentries *bootentries_alloc(void);
|
||||
void bootentries_free(struct bootentries *bootentries);
|
||||
int bootentry_create_from_name(struct bootentries *bootentries,
|
||||
const char *name);
|
||||
void bootsources_menu(struct bootentries *bootentries, int timeout);
|
||||
void bootsources_list(struct bootentries *bootentries);
|
||||
int boot_entry(struct bootentry *be, int verbose, int dryrun);
|
||||
|
||||
#endif /* __BOOT_H */
|
||||
|
|
Loading…
Reference in New Issue