summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boards/archosg9/archos_features.c3
-rw-r--r--arch/arm/lib/bootm.c1
-rw-r--r--arch/arm/mach-omap/omap_generic.c2
-rw-r--r--arch/blackfin/lib/blackfin_linux.c1
-rw-r--r--arch/efi/efi/efi-image.c1
-rw-r--r--arch/mips/lib/bootm.c1
-rw-r--r--arch/nios2/lib/bootm.c1
-rw-r--r--arch/ppc/lib/ppclinux.c1
-rw-r--r--commands/Kconfig1
-rw-r--r--commands/boot.c415
-rw-r--r--commands/bootm.c2
-rw-r--r--common/Kconfig3
-rw-r--r--common/Makefile1
-rw-r--r--common/blspec.c343
-rw-r--r--common/boot.c339
-rw-r--r--common/bootm.c3
-rw-r--r--common/image-fit.c2
-rw-r--r--drivers/usb/gadget/f_fastboot.c2
-rw-r--r--include/blspec.h91
-rw-r--r--include/boot.h139
-rw-r--r--include/bootm.h125
-rw-r--r--include/image-fit.h2
22 files changed, 683 insertions, 796 deletions
diff --git a/arch/arm/boards/archosg9/archos_features.c b/arch/arm/boards/archosg9/archos_features.c
index b39673420c..0cffac7780 100644
--- a/arch/arm/boards/archosg9/archos_features.c
+++ b/arch/arm/boards/archosg9/archos_features.c
@@ -9,8 +9,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
-#include <boot.h>
+#include <common.h>
#include <asm/setup.h>
#include "archos_features.h"
#include "feature_list.h"
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 252946ce5a..404a6ae6ad 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -1,3 +1,4 @@
+#include <bootm.h>
#include <boot.h>
#include <common.h>
#include <command.h>
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index d27c7a867f..1d03eac119 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -15,7 +15,7 @@
#include <common.h>
#include <bootsource.h>
#include <envfs.h>
-#include <boot.h>
+#include <bootm.h>
#include <init.h>
#include <io.h>
#include <fs.h>
diff --git a/arch/blackfin/lib/blackfin_linux.c b/arch/blackfin/lib/blackfin_linux.c
index da2f78bcb5..5ebd284d16 100644
--- a/arch/blackfin/lib/blackfin_linux.c
+++ b/arch/blackfin/lib/blackfin_linux.c
@@ -33,6 +33,7 @@
#include <errno.h>
#include <init.h>
#include <boot.h>
+#include <bootm.h>
#define CMD_LINE_ADDR 0xFF900000 /* L1 scratchpad */
diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c
index c78043b0de..32e060886a 100644
--- a/arch/efi/efi/efi-image.c
+++ b/arch/efi/efi/efi-image.c
@@ -31,6 +31,7 @@
#include <string.h>
#include <linux/err.h>
#include <boot.h>
+#include <bootm.h>
#include <fs.h>
#include <libfile.h>
#include <binfmt.h>
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 6702372333..91e7e1c68a 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -1,4 +1,5 @@
#include <boot.h>
+#include <bootm.h>
#include <common.h>
#include <libfile.h>
#include <malloc.h>
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index ac70330729..34908bde33 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -27,6 +27,7 @@
#include <environment.h>
#include <init.h>
#include <boot.h>
+#include <bootm.h>
#include <errno.h>
#include <asm/cache.h>
diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c
index a36682caf2..3fca6b2720 100644
--- a/arch/ppc/lib/ppclinux.c
+++ b/arch/ppc/lib/ppclinux.c
@@ -9,6 +9,7 @@
#include <asm/bitops.h>
#include <asm/processor.h>
#include <boot.h>
+#include <bootm.h>
#include <errno.h>
#include <restart.h>
#include <fs.h>
diff --git a/commands/Kconfig b/commands/Kconfig
index 17020b2401..decd45d761 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -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
diff --git a/commands/boot.c b/commands/boot.c
index c091b2e1fa..8b3b407e12 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -11,378 +11,23 @@
*
*/
-#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 <boot.h>
-#include <glob.h>
-#include <init.h>
-#include <menu.h>
-#include <fs.h>
#include <complete.h>
#include <linux/stat.h>
-static int verbose;
-static int dryrun;
-static int timeout;
-
-/*
- * Start a single boot script. 'path' is a full path to a boot script.
- */
-static int boot_script(char *path)
-{
- int ret;
- struct bootm_data data = {};
-
- globalvar_set_match("linux.bootargs.dyn.", "");
-
- ret = run_command(path);
- if (ret) {
- printf("Running %s failed\n", path);
- 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(path), 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 blspec_entry *be)
-{
- int ret;
-
- 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));
- }
-
- if (be->scriptpath) {
- ret = boot_script(be->scriptpath);
- } else {
- if (IS_ENABLED(CONFIG_BLSPEC))
- ret = blspec_boot(be, verbose, dryrun);
- else
- ret = -ENOSYS;
- }
-
- return ret;
-}
-
-static void bootsource_action(struct menu *m, struct menu_entry *me)
-{
- struct blspec_entry *be = container_of(me, struct blspec_entry, 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();
-}
-
-/*
- * bootscript_create_entry - create a boot entry from a script name
- */
-static int bootscript_create_entry(struct blspec *blspec, const char *name)
-{
- struct blspec_entry *be;
- enum filetype type;
-
- type = file_name_detect_type(name);
- if (type != filetype_sh)
- return -EINVAL;
-
- be = blspec_entry_alloc(blspec);
- be->me.type = MENU_ENTRY_NORMAL;
- be->scriptpath = xstrdup(name);
- be->me.display = xstrdup(basename(be->scriptpath));
-
- 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 blspec *blspec, 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(blspec, 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(blspec, 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 blspec *blspec, const char *name)
-{
- int found = 0, ret;
-
- if (IS_ENABLED(CONFIG_BLSPEC)) {
- ret = blspec_scan_devicename(blspec, name);
- if (ret > 0)
- found += ret;
- ret = blspec_scan_directory(blspec, 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(blspec, path);
- if (ret > 0)
- found += ret;
-
- free(path);
- }
-
- return found;
-}
-
-/*
- * bootentries_collect - collect bootentries from an array of names
- */
-static struct blspec *bootentries_collect(char *entries[], int num_entries)
-{
- struct blspec *blspec;
- int i;
-
- blspec = blspec_alloc();
-
- if (IS_ENABLED(CONFIG_MENU))
- blspec->menu->display = basprintf("boot");
-
- if (!num_entries)
- bootscript_scan_path(blspec, "/env/boot");
-
- if (IS_ENABLED(CONFIG_BLSPEC) && !num_entries)
- blspec_scan_devices(blspec);
-
- for (i = 0; i < num_entries; i++)
- bootentry_parse_one(blspec, entries[i]);
-
- return blspec;
-}
-
-/*
- * bootsources_menu - show a menu from an array of names
- */
-static void bootsources_menu(char *entries[], int num_entries)
-{
- struct blspec *blspec = NULL;
- struct blspec_entry *entry, *entry_default;
- struct menu_entry *back_entry;
-
- if (!IS_ENABLED(CONFIG_MENU)) {
- printf("no menu support available\n");
- return;
- }
-
- blspec = bootentries_collect(entries, num_entries);
- if (!blspec)
- return;
-
- entry_default = blspec_entry_default(blspec);
-
- blspec_for_each_entry(blspec, entry) {
- entry->me.action = bootsource_action;
- menu_add_entry(blspec->menu, &entry->me);
- if (entry == entry_default)
- menu_set_selected_entry(blspec->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(blspec->menu, back_entry);
-
- if (timeout >= 0)
- blspec->menu->auto_select = timeout;
-
- menu_show(blspec->menu);
-
- free(back_entry);
-
- blspec_free(blspec);
-}
-
-/*
- * bootsources_list - list boot entries from an array of names
- */
-static void bootsources_list(char *entries[], int num_entries)
-{
- struct blspec *blspec;
- struct blspec_entry *entry, *entry_default;
-
- blspec = bootentries_collect(entries, num_entries);
- if (!blspec)
- return;
-
- entry_default = blspec_entry_default(blspec);
-
- printf(" %-20s %-20s %s\n", "device", "hwdevice", "title");
- printf(" %-20s %-20s %s\n", "------", "--------", "-----");
-
- blspec_for_each_entry(blspec, entry) {
- if (entry == entry_default)
- printf("* ");
- else
- printf(" ");
-
- if (entry->scriptpath)
- printf("%-40s %s\n", basename(entry->scriptpath), entry->me.display);
- else
- printf("%s\n", entry->me.display);
- }
-
- blspec_free(blspec);
-}
-
-/*
- * boot a script or a bootspec entry. 'name' can be:
- * - a filename under /env/boot/
- * - a full path to a boot script
- * - a device name
- * - a partition name under /dev/
- * - a full path to a directory which
- * - contains boot scripts, or
- * - contains a loader/entries/ directory containing bootspec entries
- *
- * Returns a negative error on failure, or 0 on a successful dryrun boot.
- */
-static int boot(const char *name)
-{
- struct blspec *blspec;
- struct blspec_entry *entry, *entry_default;
- int ret;
-
- blspec = blspec_alloc();
- ret = bootentry_parse_one(blspec, name);
- if (ret < 0)
- return ret;
-
- if (!ret) {
- printf("Nothing bootable found on %s\n", name);
- return -ENOENT;
- }
-
- entry_default = blspec_entry_default(blspec);
- if (entry_default) {
- ret = boot_entry(entry_default);
- if (!ret)
- return ret;
- printf("booting %s failed: %s\n", entry_default->me.display,
- strerror(-ret));
- }
-
- blspec_for_each_entry(blspec, entry) {
- if (entry == entry_default)
- continue;
-
- printf("booting %s\n", entry->me.display);
- ret = boot_entry(entry);
- if (!ret)
- break;
- printf("booting %s failed: %s\n", entry->me.display, strerror(-ret));
- }
-
- return ret;
-}
-
static int do_boot(int argc, char *argv[])
{
char *freep = NULL;
int opt, ret = 0, do_list = 0, do_menu = 0;
- char **sources;
- int num_sources;
- int i;
+ int i, dryrun = 0, verbose = 0, timeout = -1;
+ struct bootentries *entries;
+ struct bootentry *entry;
verbose = 0;
dryrun = 0;
@@ -406,17 +51,22 @@ 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;
}
}
+ entries = bootentries_alloc();
+
if (optind < argc) {
- num_sources = argc - optind;
- sources = xmemdup(&argv[optind], sizeof(char *) * num_sources);
+ for (i = optind; i < argc; i++) {
+ ret = bootentry_create_from_name(entries, argv[i]);
+ if (ret <= 0)
+ printf("Nothing bootable found on '%s'\n", argv[i]);
+ }
} else {
const char *def;
- char *sep;
+ char *sep, *name;
def = getenv("global.boot.default");
if (!def)
@@ -424,49 +74,38 @@ static int do_boot(int argc, char *argv[])
sep = freep = xstrdup(def);
- num_sources = 0;
-
- while (1) {
- num_sources++;
-
- sep = strchr(sep, ' ');
- if (!sep)
- break;
- sep++;
+ while ((name = strsep(&sep, " ")) != NULL) {
+ ret = bootentry_create_from_name(entries, name);
+ if (ret <= 0)
+ printf("Nothing bootable found on '%s'\n", name);
}
- sources = xmalloc(sizeof(char *) * num_sources);
-
- sep = freep;
+ free(freep);
+ }
- for (i = 0; i < num_sources; i++) {
- sources[i] = sep;
- sep = strchr(sep, ' ');
- if (sep)
- *sep = 0;
- sep++;
- }
+ if (list_empty(&entries->entries)) {
+ printf("Nothing bootable found\n");
+ return COMMAND_ERROR;
}
if (do_list) {
- bootsources_list(sources, num_sources);
+ bootsources_list(entries);
goto out;
}
if (do_menu) {
- bootsources_menu(sources, num_sources);
+ bootsources_menu(entries, timeout);
goto out;
}
- for (i = 0; i < num_sources; i++) {
- ret = boot(sources[i]);
+ bootentries_for_each_entry(entries, entry) {
+ ret = boot_entry(entry, verbose, dryrun);
if (!ret)
break;
}
out:
- free(sources);
- free(freep);
+ bootentries_free(entries);
return ret;
}
@@ -504,5 +143,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");
diff --git a/commands/bootm.c b/commands/bootm.c
index 6bedb007b5..61b9086a15 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -32,7 +32,7 @@
#include <fcntl.h>
#include <fs.h>
#include <errno.h>
-#include <boot.h>
+#include <bootm.h>
#include <of.h>
#include <rtc.h>
#include <init.h>
diff --git a/common/Kconfig b/common/Kconfig
index 6ce2a76afa..832634047f 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -110,6 +110,9 @@ config UBIFORMAT
depends on MTD_UBI
default y
+config BOOT
+ bool
+
menu "General Settings"
config LOCALVERSION
diff --git a/common/Makefile b/common/Makefile
index 17fcb5f24a..00bc0e8834 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -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
diff --git a/common/blspec.c b/common/blspec.c
index bf98e6b29a..f02f5e9ce3 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -24,7 +24,7 @@
#include <libfile.h>
#include <libbb.h>
#include <init.h>
-#include <boot.h>
+#include <bootm.h>
#include <net.h>
#include <fs.h>
#include <of.h>
@@ -43,6 +43,84 @@ int blspec_entry_var_set(struct blspec_entry *entry, const char *name,
}
/*
+ * blspec_boot - boot an entry
+ *
+ * This boots an entry. On success this function does not return.
+ * In case of an error the error code is returned. This function may
+ * return 0 in case of a succesful dry run.
+ */
+static int blspec_boot(struct bootentry *be, int verbose, int dryrun)
+{
+ struct blspec_entry *entry = container_of(be, struct blspec_entry, entry);
+ int ret;
+ const char *abspath, *devicetree, *options, *initrd, *linuximage;
+ const char *appendroot;
+ struct bootm_data data = {
+ .initrd_address = UIMAGE_INVALID_ADDRESS,
+ .os_address = UIMAGE_SOME_ADDRESS,
+ .verbose = verbose,
+ .dryrun = dryrun,
+ };
+
+ globalvar_set_match("linux.bootargs.dyn.", "");
+ globalvar_set_match("bootm.", "");
+
+ devicetree = blspec_entry_var_get(entry, "devicetree");
+ initrd = blspec_entry_var_get(entry, "initrd");
+ options = blspec_entry_var_get(entry, "options");
+ linuximage = blspec_entry_var_get(entry, "linux");
+
+ if (entry->rootpath)
+ abspath = entry->rootpath;
+ else
+ abspath = "";
+
+ data.os_file = basprintf("%s/%s", abspath, linuximage);
+
+ if (devicetree) {
+ if (!strcmp(devicetree, "none")) {
+ struct device_node *node = of_get_root_node();
+ if (node)
+ of_delete_node(node);
+ } else {
+ data.oftree_file = basprintf("%s/%s", abspath,
+ devicetree);
+ }
+ }
+
+ if (initrd)
+ data.initrd_file = basprintf("%s/%s", abspath, initrd);
+
+ globalvar_add_simple("linux.bootargs.dyn.bootentries", options);
+
+ appendroot = blspec_entry_var_get(entry, "linux-appendroot");
+ if (appendroot) {
+ int val;
+
+ ret = strtobool(appendroot, &val);
+ if (ret) {
+ pr_err("Invalid value \"%s\" for appendroot option\n",
+ appendroot);
+ goto err_out;
+ }
+ data.appendroot = val;
+ }
+
+ pr_info("booting %s from %s\n", blspec_entry_var_get(entry, "title"),
+ entry->cdev ? dev_name(entry->cdev->dev) : "none");
+
+ ret = bootm_boot(&data);
+ if (ret)
+ pr_err("Booting failed\n");
+err_out:
+ free((char *)data.oftree_file);
+ free((char *)data.initrd_file);
+ free((char *)data.os_file);
+
+ return ret;
+}
+
+/*
* blspec_entry_var_get - get the value of a variable
*/
const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name)
@@ -55,10 +133,33 @@ const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name)
return ret ? NULL : str;
}
+static void blspec_entry_free(struct bootentry *be)
+{
+ struct blspec_entry *entry = container_of(be, struct blspec_entry, entry);
+
+ of_delete_node(entry->node);
+ free(entry->configpath);
+ free(entry->rootpath);
+ free(entry);
+}
+
+static struct blspec_entry *blspec_entry_alloc(struct bootentries *bootentries)
+{
+ struct blspec_entry *entry;
+
+ entry = xzalloc(sizeof(*entry));
+
+ entry->node = of_new_node(NULL, NULL);
+ entry->entry.release = blspec_entry_free;
+ entry->entry.boot = blspec_boot;
+
+ return entry;
+}
+
/*
* blspec_entry_open - open an entry given a path
*/
-static struct blspec_entry *blspec_entry_open(struct blspec *blspec,
+static struct blspec_entry *blspec_entry_open(struct bootentries *bootentries,
const char *abspath)
{
struct blspec_entry *entry;
@@ -71,7 +172,7 @@ static struct blspec_entry *blspec_entry_open(struct blspec *blspec,
if (!buf)
return ERR_PTR(-errno);
- entry = blspec_entry_alloc(blspec);
+ entry = blspec_entry_alloc(bootentries);
next = buf;
@@ -126,11 +227,13 @@ static struct blspec_entry *blspec_entry_open(struct blspec *blspec,
* blspec_have_entry - check if we already have an entry with
* a certain path
*/
-static int blspec_have_entry(struct blspec *blspec, const char *path)
+static int blspec_have_entry(struct bootentries *bootentries, const char *path)
{
+ struct bootentry *be;
struct blspec_entry *e;
- list_for_each_entry(e, &blspec->entries, list) {
+ list_for_each_entry(be, &bootentries->entries, list) {
+ e = container_of(be, struct blspec_entry, entry);
if (e->configpath && !strcmp(e->configpath, path))
return 1;
}
@@ -210,7 +313,7 @@ static char *parse_nfs_url(const char *url)
if (prevpath) {
mountpath = xstrdup(prevpath);
} else {
- mountpath = basprintf("/mnt/nfs-%s-blspec-%08x", host,
+ mountpath = basprintf("/mnt/nfs-%s-bootentries-%08x", host,
rand());
if (port)
options = basprintf("mountport=%s,port=%s", port,
@@ -317,11 +420,11 @@ out:
/*
* blspec_scan_directory - scan over a directory
*
- * Given a root path collects all blspec entries found under /blspec/entries/.
+ * Given a root path collects all bootentries entries found under /bootentries/entries/.
*
* returns the number of entries found or a negative error value otherwise.
*/
-int blspec_scan_directory(struct blspec *blspec, const char *root)
+int blspec_scan_directory(struct bootentries *bootentries, const char *root)
{
struct blspec_entry *entry;
DIR *dir;
@@ -329,16 +432,13 @@ int blspec_scan_directory(struct blspec *blspec, const char *root)
char *abspath;
int ret, found = 0;
const char *dirname = "loader/entries";
- char *entry_default = NULL, *entry_once = NULL, *name, *nfspath = NULL;
+ char *nfspath = NULL;
nfspath = parse_nfs_url(root);
if (!IS_ERR(nfspath))
root = nfspath;
- pr_info("%s: %s %s\n", __func__, root, dirname);
-
- entry_default = read_file_line("%s/default", root);
- entry_once = read_file_line("%s/once", root);
+ pr_debug("%s: %s %s\n", __func__, root, dirname);
abspath = basprintf("%s/%s", root, dirname);
@@ -382,12 +482,12 @@ int blspec_scan_directory(struct blspec *blspec, const char *root)
continue;
}
- if (blspec_have_entry(blspec, configname)) {
+ if (blspec_have_entry(bootentries, configname)) {
free(configname);
continue;
}
- entry = blspec_entry_open(blspec, configname);
+ entry = blspec_entry_open(bootentries, configname);
if (IS_ERR(entry)) {
free(configname);
continue;
@@ -398,34 +498,29 @@ int blspec_scan_directory(struct blspec *blspec, const char *root)
entry->cdev = get_cdev_by_mountpath(root);
if (!entry_is_of_compatible(entry)) {
- blspec_entry_free(entry);
+ blspec_entry_free(&entry->entry);
continue;
}
found++;
- name = basprintf("%s/%s", dirname, d->d_name);
- if (entry_default && !strcmp(name, entry_default))
- entry->boot_default = true;
- if (entry_once && !strcmp(name, entry_once))
- entry->boot_once = true;
- free(name);
-
if (entry->cdev) {
devname = xstrdup(dev_name(entry->cdev->dev));
if (entry->cdev->dev->parent)
hwdevname = xstrdup(dev_name(entry->cdev->dev->parent));
}
- entry->me.display = basprintf("%-20s %-20s %s",
- devname ? devname : "",
- hwdevname ? hwdevname : "",
- blspec_entry_var_get(entry, "title"));
-
+ entry->entry.title = xstrdup(blspec_entry_var_get(entry, "title"));
+ entry->entry.description = basprintf("blspec entry, device: %s hwdevice: %s",
+ devname ? devname : "none",
+ hwdevname ? hwdevname : "none");
free(devname);
free(hwdevname);
- entry->me.type = MENU_ENTRY_NORMAL;
+ entry->entry.me.type = MENU_ENTRY_NORMAL;
+ entry->entry.release = blspec_entry_free;
+
+ bootentries_add_entry(bootentries, &entry->entry);
}
ret = found;
@@ -435,8 +530,6 @@ err_out:
if (!IS_ERR(nfspath))
free(nfspath);
free(abspath);
- free(entry_default);
- free(entry_once);
return ret;
}
@@ -444,13 +537,13 @@ err_out:
/*
* blspec_scan_ubi - scan over a cdev containing UBI volumes
*
- * This function attaches a cdev as UBI devices and collects all blspec
+ * This function attaches a cdev as UBI devices and collects all bootentries
* entries found in the UBI volumes
*
* returns the number of entries found or a negative error code if some unexpected
* error occured.
*/
-static int blspec_scan_ubi(struct blspec *blspec, struct cdev *cdev)
+static int blspec_scan_ubi(struct bootentries *bootentries, struct cdev *cdev)
{
struct device_d *child;
int ret, found = 0;
@@ -462,7 +555,7 @@ static int blspec_scan_ubi(struct blspec *blspec, struct cdev *cdev)
return 0;
device_for_each_child(cdev->dev, child) {
- ret = blspec_scan_device(blspec, child);
+ ret = blspec_scan_device(bootentries, child);
if (ret > 0)
found += ret;
}
@@ -473,13 +566,13 @@ static int blspec_scan_ubi(struct blspec *blspec, struct cdev *cdev)
/*
* blspec_scan_cdev - scan over a cdev
*
- * Given a cdev this function mounts the filesystem and collects all blspec
- * entries found under /blspec/entries/.
+ * Given a cdev this function mounts the filesystem and collects all bootentries
+ * entries found under /bootentries/entries/.
*
* returns the number of entries found or a negative error code if some unexpected
* error occured.
*/
-static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev)
+static int blspec_scan_cdev(struct bootentries *bootentries, struct cdev *cdev)
{
int ret, found = 0;
void *buf = xzalloc(512);
@@ -502,14 +595,14 @@ static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev)
return -EINVAL;
if (filetype == filetype_ubi && IS_ENABLED(CONFIG_MTD_UBI)) {
- ret = blspec_scan_ubi(blspec, cdev);
+ ret = blspec_scan_ubi(bootentries, cdev);
if (ret > 0)
found += ret;
}
rootpath = cdev_mount_default(cdev, NULL);
if (!IS_ERR(rootpath)) {
- ret = blspec_scan_directory(blspec, rootpath);
+ ret = blspec_scan_directory(bootentries, rootpath);
if (ret > 0)
found += ret;
}
@@ -524,7 +617,7 @@ static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev)
* Returns the number of entries found or a negative error code if some unexpected
* error occured.
*/
-int blspec_scan_devices(struct blspec *blspec)
+int blspec_scan_devices(struct bootentries *bootentries)
{
struct device_d *dev;
struct block_device *bdev;
@@ -537,7 +630,7 @@ int blspec_scan_devices(struct blspec *blspec)
struct cdev *cdev = &bdev->cdev;
list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list) {
- ret = blspec_scan_cdev(blspec, cdev);
+ ret = blspec_scan_cdev(bootentries, cdev);
if (ret > 0)
found += ret;
}
@@ -550,11 +643,11 @@ int blspec_scan_devices(struct blspec *blspec)
* blspec_scan_device - scan a device for child cdevs
*
* Given a device this functions scans over all child cdevs looking
- * for blspec entries.
+ * for bootentries entries.
* Returns the number of entries found or a negative error code if some unexpected
* error occured.
*/
-int blspec_scan_device(struct blspec *blspec, struct device_d *dev)
+int blspec_scan_device(struct bootentries *bootentries, struct device_d *dev)
{
struct device_d *child;
struct cdev *cdev;
@@ -571,7 +664,7 @@ int blspec_scan_device(struct blspec *blspec, struct device_d *dev)
* should be used as $BOOT
*/
if (cdev->dos_partition_type == 0xea) {
- ret = blspec_scan_cdev(blspec, cdev);
+ ret = blspec_scan_cdev(bootentries, cdev);
if (ret == 0)
ret = -ENOENT;
@@ -590,7 +683,7 @@ int blspec_scan_device(struct blspec *blspec, struct device_d *dev)
/* Try child devices */
device_for_each_child(dev, child) {
- ret = blspec_scan_device(blspec, child);
+ ret = blspec_scan_device(bootentries, child);
if (ret > 0)
return ret;
}
@@ -600,7 +693,7 @@ int blspec_scan_device(struct blspec *blspec, struct device_d *dev)
* by the bootblspec spec).
*/
list_for_each_entry(cdev, &dev->cdevs, devices_list) {
- ret = blspec_scan_cdev(blspec, cdev);
+ ret = blspec_scan_cdev(bootentries, cdev);
if (ret > 0)
found += ret;
}
@@ -612,11 +705,11 @@ int blspec_scan_device(struct blspec *blspec, struct device_d *dev)
* blspec_scan_devicename - scan a hardware device for child cdevs
*
* Given a name of a hardware device this functions scans over all child
- * cdevs looking for blspec entries.
+ * cdevs looking for bootentries entries.
* Returns the number of entries found or a negative error code if some unexpected
* error occured.
*/
-int blspec_scan_devicename(struct blspec *blspec, const char *devname)
+int blspec_scan_devicename(struct bootentries *bootentries, const char *devname)
{
struct device_d *dev;
struct cdev *cdev;
@@ -627,7 +720,7 @@ int blspec_scan_devicename(struct blspec *blspec, const char *devname)
cdev = cdev_by_name(devname);
if (cdev) {
- int ret = blspec_scan_cdev(blspec, cdev);
+ int ret = blspec_scan_cdev(bootentries, cdev);
if (ret > 0)
return ret;
}
@@ -636,155 +729,5 @@ int blspec_scan_devicename(struct blspec *blspec, const char *devname)
if (!dev)
return -ENODEV;
- return blspec_scan_device(blspec, dev);
-}
-
-/*
- * blspec_boot - boot an entry
- *
- * This boots an entry. On success this function does not return.
- * In case of an error the error code is returned. This function may
- * return 0 in case of a succesful dry run.
- */
-int blspec_boot(struct blspec_entry *entry, int verbose, int dryrun)
-{
- int ret;
- const char *abspath, *devicetree, *options, *initrd, *linuximage;
- const char *appendroot;
- struct bootm_data data = {
- .initrd_address = UIMAGE_INVALID_ADDRESS,
- .os_address = UIMAGE_SOME_ADDRESS,
- .verbose = verbose,
- .dryrun = dryrun,
- };
-
- globalvar_set_match("linux.bootargs.dyn.", "");
- globalvar_set_match("bootm.", "");
-
- devicetree = blspec_entry_var_get(entry, "devicetree");
- initrd = blspec_entry_var_get(entry, "initrd");
- options = blspec_entry_var_get(entry, "options");
- linuximage = blspec_entry_var_get(entry, "linux");
-
- if (entry->rootpath)
- abspath = entry->rootpath;
- else
- abspath = "";
-
- data.os_file = basprintf("%s/%s", abspath, linuximage);
-
- if (devicetree) {
- if (!strcmp(devicetree, "none")) {
- struct device_node *node = of_get_root_node();
- if (node)
- of_delete_node(node);
- } else {
- data.oftree_file = basprintf("%s/%s", abspath,
- devicetree);
- }
- }
-
- if (initrd)
- data.initrd_file = basprintf("%s/%s", abspath, initrd);
-
- globalvar_add_simple("linux.bootargs.dyn.blspec", options);
-
- appendroot = blspec_entry_var_get(entry, "linux-appendroot");
- if (appendroot) {
- int val;
-
- ret = strtobool(appendroot, &val);
- if (ret) {
- pr_err("Invalid value \"%s\" for appendroot option\n",
- appendroot);
- goto err_out;
- }
- data.appendroot = val;
- }
-
- pr_info("booting %s from %s\n", blspec_entry_var_get(entry, "title"),
- entry->cdev ? dev_name(entry->cdev->dev) : "none");
-
- if (entry->boot_once) {
- char *s = basprintf("%s/once", abspath);
-
- ret = unlink(s);
- if (ret)
- pr_err("unable to unlink 'once': %s\n", strerror(-ret));
- else
- pr_info("removed 'once'\n");
-
- free(s);
- }
-
- ret = bootm_boot(&data);
- if (ret)
- pr_err("Booting failed\n");
-err_out:
- free((char *)data.oftree_file);
- free((char *)data.initrd_file);
- free((char *)data.os_file);
-
- return ret;
-}
-
-/*
- * blspec_entry_default - find the entry to load.
- *
- * return in the order of precendence:
- * - The entry specified in the 'once' file
- * - The entry specified in the 'default' file
- * - The first entry
- */
-struct blspec_entry *blspec_entry_default(struct blspec *l)
-{
- struct blspec_entry *entry_once = NULL;
- struct blspec_entry *entry_default = NULL;
- struct blspec_entry *entry_first = NULL;
- struct blspec_entry *e;
-
- list_for_each_entry(e, &l->entries, list) {
- if (!entry_first)
- entry_first = e;
- if (e->boot_once)
- entry_once = e;
- if (e->boot_default)
- entry_default = e;
- }
-
- if (entry_once)
- return entry_once;
- if (entry_default)
- return entry_default;
- return entry_first;
-}
-
-/*
- * blspec_boot_devicename - scan hardware device for blspec entries and
- * start the best one.
- */
-int blspec_boot_devicename(const char *devname, int verbose, int dryrun)
-{
- struct blspec *blspec;
- struct blspec_entry *e;
- int ret;
-
- blspec = blspec_alloc();
-
- ret = blspec_scan_devicename(blspec, devname);
- if (ret)
- return ret;
-
- e = blspec_entry_default(blspec);
- if (!e) {
- printf("No bootspec entry found on %s\n", devname);
- ret = -ENOENT;
- goto out;
- }
-
- ret = blspec_boot(e, verbose, dryrun);
-out:
- blspec_free(blspec);
-
- return ret;
+ return blspec_scan_device(bootentries, dev);
}
diff --git a/common/boot.c b/common/boot.c
new file mode 100644
index 0000000000..e66bacbb0e
--- /dev/null
+++ b/common/boot.c
@@ -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");
diff --git a/common/bootm.c b/common/bootm.c
index 27d20f2c72..78d04d5806 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -12,7 +12,7 @@
*/
#include <common.h>
-#include <boot.h>
+#include <bootm.h>
#include <fs.h>
#include <malloc.h>
#include <memory.h>
@@ -20,6 +20,7 @@
#include <image-fit.h>
#include <globalvar.h>
#include <init.h>
+#include <environment.h>
#include <linux/stat.h>
#include <magicvar.h>
diff --git a/common/image-fit.c b/common/image-fit.c
index 9b6c40fbf8..6a01c614cc 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -20,7 +20,7 @@
#define pr_fmt(fmt) "FIT: " fmt
#include <common.h>
#include <init.h>
-#include <boot.h>
+#include <bootm.h>
#include <libfile.h>
#include <fdt.h>
#include <digest.h>
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 6db7dafd9b..a6192b9ebd 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -25,7 +25,7 @@
#include <ioctl.h>
#include <libbb.h>
#include <bbu.h>
-#include <boot.h>
+#include <bootm.h>
#include <dma.h>
#include <fs.h>
#include <libfile.h>
diff --git a/include/blspec.h b/include/blspec.h
index e22e9be11d..7d911f030b 100644
--- a/include/blspec.h
+++ b/include/blspec.h
@@ -2,102 +2,25 @@
#define __LOADER_H__
#include <linux/list.h>
-#include <menu.h>
-
-struct blspec {
- struct list_head entries;
- struct menu *menu;
-};
+#include <boot.h>
struct blspec_entry {
- struct list_head list;
+ struct bootentry entry;
+
struct device_node *node;
struct cdev *cdev;
char *rootpath;
char *configpath;
- bool boot_default;
- bool boot_once;
-
- struct menu_entry me;
-
- char *scriptpath;
};
int blspec_entry_var_set(struct blspec_entry *entry, const char *name,
const char *val);
const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name);
-int blspec_entry_save(struct blspec_entry *entry, const char *path);
-
-int blspec_boot(struct blspec_entry *entry, int verbose, int dryrun);
-
-int blspec_boot_devicename(const char *devname, int verbose, int dryrun);
-
-int blspec_scan_devices(struct blspec *blspec);
-
-int blspec_scan_device(struct blspec *blspec, struct device_d *dev);
-int blspec_scan_devicename(struct blspec *blspec, const char *devname);
-int blspec_scan_directory(struct blspec *blspec, const char *root);
-
-#define blspec_for_each_entry(blspec, entry) \
- list_for_each_entry(entry, &blspec->entries, list)
-
-static inline struct blspec_entry *blspec_entry_alloc(struct blspec *blspec)
-{
- struct blspec_entry *entry;
-
- entry = xzalloc(sizeof(*entry));
-
- entry->node = of_new_node(NULL, NULL);
-
- list_add_tail(&entry->list, &blspec->entries);
-
- return entry;
-}
-
-static inline void blspec_entry_free(struct blspec_entry *entry)
-{
- list_del(&entry->list);
- of_delete_node(entry->node);
- free(entry->me.display);
- free(entry->scriptpath);
- free(entry->configpath);
- free(entry->rootpath);
- free(entry);
-}
-
-static inline struct blspec *blspec_alloc(void)
-{
- struct blspec *blspec;
-
- blspec = xzalloc(sizeof(*blspec));
- INIT_LIST_HEAD(&blspec->entries);
-
- if (IS_ENABLED(CONFIG_MENU))
- blspec->menu = menu_alloc();
-
- return blspec;
-}
-
-static inline void blspec_free(struct blspec *blspec)
-{
- struct blspec_entry *entry, *tmp;
-
- list_for_each_entry_safe(entry, tmp, &blspec->entries, list)
- blspec_entry_free(entry);
- if (blspec->menu)
- free(blspec->menu->display);
- free(blspec->menu);
- free(blspec);
-}
+int blspec_scan_devices(struct bootentries *bootentries);
-#ifdef CONFIG_BLSPEC
-struct blspec_entry *blspec_entry_default(struct blspec *l);
-#else
-static inline struct blspec_entry *blspec_entry_default(struct blspec *l)
-{
- return NULL;
-}
-#endif
+int blspec_scan_device(struct bootentries *bootentries, struct device_d *dev);
+int blspec_scan_devicename(struct bootentries *bootentries, const char *devname);
+int blspec_scan_directory(struct bootentries *bootentries, const char *root);
#endif /* __LOADER_H__ */
diff --git a/include/boot.h b/include/boot.h
index 8e7a9f11d4..a855cbe1e5 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -1,115 +1,10 @@
#ifndef __BOOT_H
#define __BOOT_H
-#include <image.h>
-#include <filetype.h>
#include <of.h>
-#include <linux/list.h>
+#include <menu.h>
#include <environment.h>
-enum bootm_verify {
- BOOTM_VERIFY_NONE,
- BOOTM_VERIFY_HASH,
- BOOTM_VERIFY_SIGNATURE,
- BOOTM_VERIFY_AVAILABLE,
-};
-
-struct bootm_data {
- const char *os_file;
- const char *initrd_file;
- const char *oftree_file;
- int verbose;
- enum bootm_verify verify;
- bool force;
- bool dryrun;
- /*
- * appendroot - if true, try to add a suitable root= Kernel option to
- * mount the rootfs from the same device as the Kernel comes from.
- */
- bool appendroot;
- unsigned long initrd_address;
- unsigned long os_address;
- unsigned long os_entry;
-};
-
-int bootm_boot(struct bootm_data *data);
-
-struct image_data {
- /* simplest case. barebox has already loaded the os here */
- struct resource *os_res;
-
- /* if os is an uImage this will be provided */
- struct uimage_handle *os;
-
- /* if os is a FIT image this will be provided */
- struct fit_handle *os_fit;
-
- char *os_part;
-
- /* otherwise only the filename will be provided */
- char *os_file;
-
- /*
- * The address the user wants to load the os image to.
- * May be UIMAGE_INVALID_ADDRESS to indicate that the
- * user has not specified any address. In this case the
- * handler may choose a suitable address
- */
- unsigned long os_address;
-
- /* entry point to the os. relative to the start of the image */
- unsigned long os_entry;
-
- /* if initrd is already loaded this resource will be !NULL */
- struct resource *initrd_res;
-
- /* if initrd is an uImage this will be provided */
- struct uimage_handle *initrd;
- char *initrd_part;
-
- /* otherwise only the filename will be provided */
- char *initrd_file;
-
- unsigned long initrd_address;
-
- char *oftree_file;
- char *oftree_part;
-
- struct device_node *of_root_node;
- struct fdt_header *oftree;
- struct resource *oftree_res;
-
- enum bootm_verify verify;
- int verbose;
- int force;
- int dryrun;
-};
-
-struct image_handler {
- const char *name;
-
- struct list_head list;
-
- int ih_os;
-
- enum filetype filetype;
- int (*bootm)(struct image_data *data);
-};
-
-int register_image_handler(struct image_handler *handle);
-
-#ifdef CONFIG_BOOTM_VERBOSE
-static inline int bootm_verbose(struct image_data *data)
-{
- return data->verbose;
-}
-#else
-static inline int bootm_verbose(struct image_data *data)
-{
- return 0;
-}
-#endif
-
#ifdef CONFIG_FLEXIBLE_BOOTARGS
const char *linux_bootargs_get(void);
int linux_bootargs_overwrite(const char *bootargs);
@@ -125,18 +20,32 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
}
#endif
-void bootm_data_init_defaults(struct bootm_data *data);
-
-int bootm_load_os(struct image_data *data, unsigned long load_address);
+struct bootentries {
+ struct list_head entries;
+ struct menu *menu;
+};
-bool bootm_has_initrd(struct image_data *data);
-int bootm_load_initrd(struct image_data *data, unsigned long load_address);
+struct bootentry {
+ struct list_head list;
+ struct menu_entry me;
+ char *title;
+ char *description;
+ int (*boot)(struct bootentry *entry, int verbose, int dryrun);
+ void (*release)(struct bootentry *entry);
+};
-int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
-int bootm_get_os_size(struct image_data *data);
+int bootentries_add_entry(struct bootentries *entries, struct bootentry *entry);
-enum bootm_verify bootm_get_verify_mode(void);
+#define bootentries_for_each_entry(bootentries, entry) \
+ list_for_each_entry(entry, &bootentries->entries, list)
-#define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
+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 */
diff --git a/include/bootm.h b/include/bootm.h
new file mode 100644
index 0000000000..6e9777a9ac
--- /dev/null
+++ b/include/bootm.h
@@ -0,0 +1,125 @@
+#ifndef __BOOTM_H
+#define __BOOTM_H
+
+#include <image.h>
+#include <filetype.h>
+#include <linux/list.h>
+
+enum bootm_verify {
+ BOOTM_VERIFY_NONE,
+ BOOTM_VERIFY_HASH,
+ BOOTM_VERIFY_SIGNATURE,
+ BOOTM_VERIFY_AVAILABLE,
+};
+
+struct bootm_data {
+ const char *os_file;
+ const char *initrd_file;
+ const char *oftree_file;
+ int verbose;
+ enum bootm_verify verify;
+ bool force;
+ bool dryrun;
+ /*
+ * appendroot - if true, try to add a suitable root= Kernel option to
+ * mount the rootfs from the same device as the Kernel comes from.
+ */
+ bool appendroot;
+ unsigned long initrd_address;
+ unsigned long os_address;
+ unsigned long os_entry;
+};
+
+int bootm_boot(struct bootm_data *data);
+
+struct image_data {
+ /* simplest case. barebox has already loaded the os here */
+ struct resource *os_res;
+
+ /* if os is an uImage this will be provided */
+ struct uimage_handle *os;
+
+ /* if os is a FIT image this will be provided */
+ struct fit_handle *os_fit;
+
+ char *os_part;
+
+ /* otherwise only the filename will be provided */
+ char *os_file;
+
+ /*
+ * The address the user wants to load the os image to.
+ * May be UIMAGE_INVALID_ADDRESS to indicate that the
+ * user has not specified any address. In this case the
+ * handler may choose a suitable address
+ */
+ unsigned long os_address;
+
+ /* entry point to the os. relative to the start of the image */
+ unsigned long os_entry;
+
+ /* if initrd is already loaded this resource will be !NULL */
+ struct resource *initrd_res;
+
+ /* if initrd is an uImage this will be provided */
+ struct uimage_handle *initrd;
+ char *initrd_part;
+
+ /* otherwise only the filename will be provided */
+ char *initrd_file;
+
+ unsigned long initrd_address;
+
+ char *oftree_file;
+ char *oftree_part;
+
+ struct device_node *of_root_node;
+ struct fdt_header *oftree;
+ struct resource *oftree_res;
+
+ enum bootm_verify verify;
+ int verbose;
+ int force;
+ int dryrun;
+};
+
+struct image_handler {
+ const char *name;
+
+ struct list_head list;
+
+ int ih_os;
+
+ enum filetype filetype;
+ int (*bootm)(struct image_data *data);
+};
+
+int register_image_handler(struct image_handler *handle);
+
+#ifdef CONFIG_BOOTM_VERBOSE
+static inline int bootm_verbose(struct image_data *data)
+{
+ return data->verbose;
+}
+#else
+static inline int bootm_verbose(struct image_data *data)
+{
+ return 0;
+}
+#endif
+
+void bootm_data_init_defaults(struct bootm_data *data);
+
+int bootm_load_os(struct image_data *data, unsigned long load_address);
+
+bool bootm_has_initrd(struct image_data *data);
+int bootm_load_initrd(struct image_data *data, unsigned long load_address);
+
+int bootm_load_devicetree(struct image_data *data, unsigned long load_address);
+int bootm_get_os_size(struct image_data *data);
+
+enum bootm_verify bootm_get_verify_mode(void);
+
+#define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
+
+#endif /* __BOOTM_H */
diff --git a/include/image-fit.h b/include/image-fit.h
index c9d6911a97..c49f958268 100644
--- a/include/image-fit.h
+++ b/include/image-fit.h
@@ -19,7 +19,7 @@
#define __IMAGE_FIT_H__
#include <linux/types.h>
-#include <boot.h>
+#include <bootm.h>
struct fit_handle {
void *fit;