diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2016-08-03 08:08:22 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-08-03 08:08:22 +0200 |
commit | 94e7bdcd9a6a477b7bd980ac4cc168b49040884c (patch) | |
tree | 656c0007f385d49c24580f4fe8c512ac100dbe45 | |
parent | 7defdbf78f4c4c412632500c51909f08f99baacf (diff) | |
parent | eeaed6eee3d4983564e2e737b29de8fded37caf6 (diff) | |
download | barebox-94e7bdcd9a6a477b7bd980ac4cc168b49040884c.tar.gz barebox-94e7bdcd9a6a477b7bd980ac4cc168b49040884c.tar.xz |
Merge branch 'for-next/boot'
-rw-r--r-- | arch/arm/boards/archosg9/archos_features.c | 3 | ||||
-rw-r--r-- | arch/arm/lib/bootm.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap/omap_generic.c | 2 | ||||
-rw-r--r-- | arch/blackfin/lib/blackfin_linux.c | 1 | ||||
-rw-r--r-- | arch/efi/efi/efi-image.c | 1 | ||||
-rw-r--r-- | arch/mips/lib/bootm.c | 1 | ||||
-rw-r--r-- | arch/nios2/lib/bootm.c | 1 | ||||
-rw-r--r-- | arch/ppc/lib/ppclinux.c | 1 | ||||
-rw-r--r-- | commands/Kconfig | 1 | ||||
-rw-r--r-- | commands/boot.c | 415 | ||||
-rw-r--r-- | commands/bootm.c | 2 | ||||
-rw-r--r-- | common/Kconfig | 3 | ||||
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/blspec.c | 343 | ||||
-rw-r--r-- | common/boot.c | 339 | ||||
-rw-r--r-- | common/bootm.c | 3 | ||||
-rw-r--r-- | common/image-fit.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 2 | ||||
-rw-r--r-- | include/blspec.h | 91 | ||||
-rw-r--r-- | include/boot.h | 139 | ||||
-rw-r--r-- | include/bootm.h | 125 | ||||
-rw-r--r-- | include/image-fit.h | 2 |
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; |