diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-10-07 07:59:18 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-10-07 07:59:18 +0200 |
commit | e48331d6e2f37ed32dfaed1f28a36e8d796c4cea (patch) | |
tree | 48245bee05d022547480ed4d86f09202c656b699 /commands | |
parent | b32f56e7dd061ec2d938c538a5f86d22cf9a6266 (diff) | |
parent | d28c9bb55deb4146f8f98bf112d5e9aea3f08f81 (diff) | |
download | barebox-e48331d6e2f37ed32dfaed1f28a36e8d796c4cea.tar.gz barebox-e48331d6e2f37ed32dfaed1f28a36e8d796c4cea.tar.xz |
Merge branch 'for-next/bootm'
Diffstat (limited to 'commands')
-rw-r--r-- | commands/Kconfig | 11 | ||||
-rw-r--r-- | commands/Makefile | 1 | ||||
-rw-r--r-- | commands/boot.c | 258 | ||||
-rw-r--r-- | commands/bootm.c | 85 | ||||
-rw-r--r-- | commands/loads.c | 7 |
5 files changed, 289 insertions, 73 deletions
diff --git a/commands/Kconfig b/commands/Kconfig index 55e46a0392..9738ec4630 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -514,6 +514,17 @@ config CMD_LINUX16 Compile the linux16 command to be able to boot bzImages via real mode. +config CMD_BOOT + tristate + select BOOTM + prompt "boot" + help + Select this for booting based on scripts. unlike the bootm command which + can boot a single image this command offers the possibility to boot with + scripts (by default placed under /env/boot/). This command iterates over + multiple scripts until one succeeds. It supersedes the previous 'boot' + script. + config CMD_RESET tristate prompt "reset" diff --git a/commands/Makefile b/commands/Makefile index 6acffc8284..f4e0ac63a6 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -91,3 +91,4 @@ obj-$(CONFIG_CMD_FILETYPE) += filetype.o obj-$(CONFIG_CMD_BAREBOX_UPDATE)+= barebox-update.o obj-$(CONFIG_CMD_MIITOOL) += miitool.o obj-$(CONFIG_CMD_DETECT) += detect.o +obj-$(CONFIG_CMD_BOOT) += boot.o diff --git a/commands/boot.c b/commands/boot.c new file mode 100644 index 0000000000..33d1177861 --- /dev/null +++ b/commands/boot.c @@ -0,0 +1,258 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <environment.h> +#include <globalvar.h> +#include <magicvar.h> +#include <command.h> +#include <common.h> +#include <getopt.h> +#include <libgen.h> +#include <malloc.h> +#include <boot.h> +#include <fs.h> + +#include <linux/stat.h> + +static int verbose; +static int dryrun; + +static void bootsources_list(void) +{ + DIR *dir; + struct dirent *d; + const char *path = "/env/boot"; + + dir = opendir(path); + if (!dir) { + printf("cannot open %s: %s\n", path, strerror(-errno)); + return; + } + + printf("Bootsources: "); + + while ((d = readdir(dir))) { + if (*d->d_name == '.') + continue; + + printf("%s ", d->d_name); + } + + printf("\n"); + + closedir(dir); +} + +static const char *getenv_or_null(const char *var) +{ + const char *val = getenv(var); + + if (val && *val) + return val; + return NULL; +} + +/* + * Start a single boot script. 'path' is a full path to a boot script. + */ +static int boot_script(char *path) +{ + struct bootm_data data = {}; + int ret; + + printf("booting %s...\n", basename(path)); + + globalvar_set_match("linux.bootargs.dyn.", ""); + globalvar_set_match("bootm.", ""); + + ret = run_command(path, 0); + if (ret) { + printf("Running %s failed\n", path); + goto out; + } + + data.initrd_address = UIMAGE_INVALID_ADDRESS; + data.os_address = UIMAGE_SOME_ADDRESS; + data.oftree_file = getenv_or_null("global.bootm.oftree"); + data.os_file = getenv_or_null("global.bootm.image"); + getenv_ul("global.bootm.image.loadaddr", &data.os_address); + getenv_ul("global.bootm.initrd.loadaddr", &data.initrd_address); + data.initrd_file = getenv_or_null("global.bootm.initrd"); + data.verbose = verbose; + data.dryrun = dryrun; + + ret = bootm_boot(&data); + if (ret) + pr_err("Booting %s failed: %s\n", basename(path), strerror(-ret)); +out: + return ret; +} + +/* + * boot a script. 'name' can either be a filename under /env/boot/, + * a full path to a boot script or a path to a directory. This function + * returns a negative error on failure, or 0 on a successful dryrun boot. + */ +static int boot(const char *name) +{ + char *path; + DIR *dir; + struct dirent *d; + struct stat s; + int ret; + + if (*name == '/') + path = xstrdup(name); + else + path = asprintf("/env/boot/%s", name); + + ret = stat(path, &s); + if (ret) { + pr_err("%s: %s\n", path, strerror(-ret)); + goto out; + } + + if (S_ISREG(s.st_mode)) { + ret = boot_script(path); + goto out; + } + + dir = opendir(path); + if (!dir) { + ret = -errno; + printf("cannot open %s: %s\n", path, strerror(-errno)); + goto out; + } + + while ((d = readdir(dir))) { + char *file; + struct stat s; + + if (*d->d_name == '.') + continue; + + file = asprintf("%s/%s", path, d->d_name); + + ret = stat(file, &s); + if (ret) { + free(file); + continue; + } + + if (!S_ISREG(s.st_mode)) { + free(file); + continue; + } + + ret = boot_script(file); + + free(file); + + if (!ret) + break; + } + + closedir(dir); +out: + free(path); + + return ret; +} + +static int do_boot(int argc, char *argv[]) +{ + const char *sources = NULL; + char *source, *freep; + int opt, ret = 0, do_list = 0; + + verbose = 0; + dryrun = 0; + + while ((opt = getopt(argc, argv, "vld")) > 0) { + switch (opt) { + case 'v': + verbose++; + break; + case 'l': + do_list = 1; + break; + case 'd': + dryrun = 1; + break; + } + } + + if (do_list) { + bootsources_list(); + return 0; + } + + if (optind < argc) { + while (optind < argc) { + source = argv[optind]; + optind++; + ret = boot(source); + if (!ret) + break; + } + return ret; + } + + sources = getenv("global.boot.default"); + if (!sources) + return 0; + + freep = source = xstrdup(sources); + + while (1) { + char *sep = strchr(source, ' '); + if (sep) + *sep = 0; + ret = boot(source); + if (!ret) + break; + + if (sep) + source = sep + 1; + else + break; + } + + free(freep); + + return ret; +} + +BAREBOX_CMD_HELP_START(boot) +BAREBOX_CMD_HELP_USAGE("boot [OPTIONS] [BOOTSRC...]\n") +BAREBOX_CMD_HELP_SHORT("Boot an operating system.\n") +BAREBOX_CMD_HELP_SHORT("[BOOTSRC...] can be:\n") +BAREBOX_CMD_HELP_SHORT("- a filename from /env/boot/\n") +BAREBOX_CMD_HELP_SHORT("- a full path to a file\n") +BAREBOX_CMD_HELP_SHORT("- a path to a directory. All files in this directory are treated\n") +BAREBOX_CMD_HELP_SHORT(" as boot scripts.\n") +BAREBOX_CMD_HELP_SHORT("Multiple bootsources may be given which are probed in order until\n") +BAREBOX_CMD_HELP_SHORT("one succeeds.\n") +BAREBOX_CMD_HELP_SHORT("\nOptions:\n") +BAREBOX_CMD_HELP_OPT ("-v","Increase verbosity\n") +BAREBOX_CMD_HELP_OPT ("-d","Dryrun. See what happens but do no actually boot\n") +BAREBOX_CMD_HELP_OPT ("-l","List available boot sources\n") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(boot) + .cmd = do_boot, + .usage = "boot the machine", + 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 a4004dfb4c..5dff7dd674 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -46,33 +46,7 @@ #include <magicvar.h> #include <asm-generic/memory_layout.h> -/* - * Additional oftree size for the fixed tree - */ -#define OFTREE_SIZE_INCREASE 0x8000 - -static char *bootm_image_name_and_no(const char *name, int *no) -{ - char *at, *ret; - - if (!name || !*name) - return NULL; - - *no = 0; - - ret = xstrdup(name); - at = strchr(ret, '@'); - if (!at) - return ret; - - *at++ = 0; - - *no = simple_strtoul(at, NULL, 10); - - return ret; -} - -#define BOOTM_OPTS_COMMON "ca:e:vo:f" +#define BOOTM_OPTS_COMMON "ca:e:vo:fd" #ifdef CONFIG_CMD_BOOTM_INITRD #define BOOTM_OPTS BOOTM_OPTS_COMMON "L:r:" @@ -80,28 +54,13 @@ static char *bootm_image_name_and_no(const char *name, int *no) #define BOOTM_OPTS BOOTM_OPTS_COMMON #endif -unsigned long long getenv_loadaddr(const char *name) -{ - const char *valstr = getenv(name); - - if (!valstr) - return UIMAGE_SOME_ADDRESS; - - if (valstr[0] == '\0') - return UIMAGE_SOME_ADDRESS; - - return simple_strtoull(valstr, NULL, 0); -} - static int do_bootm(int argc, char *argv[]) { int opt; - struct image_data data; + struct bootm_data data = {}; int ret = 1; const char *oftree = NULL, *initrd_file = NULL, *os_file = NULL; - memset(&data, 0, sizeof(struct image_data)); - data.initrd_address = UIMAGE_INVALID_ADDRESS; data.os_address = UIMAGE_SOME_ADDRESS; data.verify = 0; @@ -109,8 +68,8 @@ static int do_bootm(int argc, char *argv[]) oftree = getenv("global.bootm.oftree"); os_file = getenv("global.bootm.image"); - data.os_address = getenv_loadaddr("global.bootm.image.loadaddr"); - data.initrd_address = getenv_loadaddr("global.bootm.initrd.loadaddr"); + getenv_ul("global.bootm.image.loadaddr", &data.os_address); + getenv_ul("global.bootm.initrd.loadaddr", &data.initrd_address); if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD)) initrd_file = getenv("global.bootm.initrd"); @@ -142,6 +101,9 @@ static int do_bootm(int argc, char *argv[]) case 'f': data.force = 1; break; + case 'd': + data.dryrun = 1; + break; default: break; } @@ -161,39 +123,28 @@ static int do_bootm(int argc, char *argv[]) if (oftree && !*oftree) oftree = NULL; - data.os_file = bootm_image_name_and_no(os_file, &data.os_num); - data.oftree_file = bootm_image_name_and_no(oftree, &data.oftree_num); - data.initrd_file = bootm_image_name_and_no(initrd_file, &data.initrd_num); + data.os_file = os_file; + data.oftree_file = oftree; + data.initrd_file = initrd_file; ret = bootm_boot(&data); + if (ret) { + printf("handler failed with: %s\n", strerror(-ret)); + goto err_out; + } - printf("handler failed with %s\n", strerror(-ret)); + if (data.dryrun) + printf("Dryrun. Aborted\n"); err_out: - free(data.initrd_file); - free(data.os_file); - - return 1; -} - -static int bootm_init(void) -{ - globalvar_add_simple("bootm.image", NULL); - globalvar_add_simple("bootm.image.loadaddr", NULL); - globalvar_add_simple("bootm.oftree", NULL); - if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD)) { - globalvar_add_simple("bootm.initrd", NULL); - globalvar_add_simple("bootm.initrd.loadaddr", NULL); - } - - return 0; + return ret ? 1 : 0; } -late_initcall(bootm_init); BAREBOX_CMD_HELP_START(bootm) BAREBOX_CMD_HELP_USAGE("bootm [OPTIONS] image\n") BAREBOX_CMD_HELP_SHORT("Boot an application image.\n") BAREBOX_CMD_HELP_OPT ("-c", "crc check uImage data\n") +BAREBOX_CMD_HELP_OPT ("-d", "dryrun. Check data, but do not run\n") #ifdef CONFIG_CMD_BOOTM_INITRD BAREBOX_CMD_HELP_OPT ("-r <initrd>","specify an initrd image\n") BAREBOX_CMD_HELP_OPT ("-L <load addr>","specify initrd load address\n") diff --git a/commands/loads.c b/commands/loads.c index bfc465bdc7..58cd24b572 100644 --- a/commands/loads.c +++ b/commands/loads.c @@ -40,14 +40,9 @@ static int do_load_serial(int argc, char *argv[]) ulong offset = 0; ulong addr; int i; - const char *env_echo; int rcode = 0; - if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) { - do_echo = 1; - } else { - do_echo = 0; - } + getenv_bool("loads_echo", &do_echo); if (argc == 2) { offset = simple_strtoul(argv[1], NULL, 16); |