diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2012-04-18 20:42:17 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2012-04-18 20:42:17 +0200 |
commit | a7ddbc40865a8ffe716aca686763780febad575c (patch) | |
tree | 66084fa9f4ac31bff8a3326198d47930f1ccf7b5 | |
parent | 030b5a1ba5bfb5cbbf8ff88f8880184b5fc76354 (diff) | |
parent | 2b26b148f4c8633a19bca0cbb96d4393ece8f54e (diff) | |
download | barebox-a7ddbc40865a8ffe716aca686763780febad575c.tar.gz barebox-a7ddbc40865a8ffe716aca686763780febad575c.tar.xz |
Merge branch 'binfmt' of git://git.jcrosoft.org/barebox into next
-rw-r--r-- | arch/arm/lib/bootm.c | 22 | ||||
-rw-r--r-- | commands/bootm.c | 12 | ||||
-rw-r--r-- | common/Kconfig | 5 | ||||
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/binfmt.c | 95 | ||||
-rw-r--r-- | common/filetype.c | 3 | ||||
-rw-r--r-- | common/hush.c | 31 | ||||
-rw-r--r-- | defaultenv/bin/boot | 4 | ||||
-rw-r--r-- | include/binfmt.h | 39 | ||||
-rw-r--r-- | include/filetype.h | 1 |
10 files changed, 200 insertions, 13 deletions
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 36f4342102..c4a50c301c 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -15,6 +15,7 @@ #include <libbb.h> #include <magicvar.h> #include <libfdt.h> +#include <binfmt.h> #include <asm/byteorder.h> #include <asm/setup.h> @@ -447,14 +448,33 @@ BAREBOX_MAGICVAR(aimage_noverwrite_bootargs, "Disable overwrite of the bootargs BAREBOX_MAGICVAR(aimage_noverwrite_tags, "Disable overwrite of the tags addr with the one present in aimage"); #endif +static struct binfmt_hook binfmt_aimage_hook = { + .type = filetype_aimage, + .exec = "bootm", +}; + +static struct binfmt_hook binfmt_arm_zimage_hook = { + .type = filetype_arm_zimage, + .exec = "bootm", +}; + +static struct binfmt_hook binfmt_barebox_hook = { + .type = filetype_arm_barebox, + .exec = "bootm", +}; + static int armlinux_register_image_handler(void) { register_image_handler(&barebox_handler); register_image_handler(&uimage_handler); register_image_handler(&rawimage_handler); register_image_handler(&zimage_handler); - if (IS_BUILTIN(CONFIG_CMD_BOOTM_AIMAGE)) + if (IS_BUILTIN(CONFIG_CMD_BOOTM_AIMAGE)) { register_image_handler(&aimage_handler); + binfmt_register(&binfmt_aimage_hook); + } + binfmt_register(&binfmt_arm_zimage_hook); + binfmt_register(&binfmt_barebox_hook); return 0; } diff --git a/commands/bootm.c b/commands/bootm.c index c89a3cc7f0..322e74fdd7 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -46,6 +46,7 @@ #include <uncompress.h> #include <memory.h> #include <filetype.h> +#include <binfmt.h> #include <asm-generic/memory_layout.h> static LIST_HEAD(handler_list); @@ -457,6 +458,17 @@ BAREBOX_CMD_END BAREBOX_MAGICVAR(bootargs, "Linux Kernel parameters"); +static struct binfmt_hook binfmt_uimage_hook = { + .type = filetype_uimage, + .exec = "bootm", +}; + +static int binfmt_uimage_init(void) +{ + return binfmt_register(&binfmt_uimage_hook); +} +fs_initcall(binfmt_uimage_init); + /** * @file * @brief Boot support for Linux diff --git a/common/Kconfig b/common/Kconfig index a997f3dc20..73d620a576 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -43,6 +43,10 @@ config HAVE_NOSHELL config FILETYPE bool +config BINFMT + bool + select FILETYPE + menu "General Settings " config LOCALVERSION @@ -275,6 +279,7 @@ choice select ENVIRONMENT_VARIABLES select COMMAND_SUPPORT select PARAMETER + select BINFMT help Enable hush support. This is the most advanced shell available for barebox. diff --git a/common/Makefile b/common/Makefile index bfde73cd44..a58aef94c8 100644 --- a/common/Makefile +++ b/common/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_BINFMT) += binfmt.o obj-$(CONFIG_SHELL_HUSH) += hush.o obj-$(CONFIG_SHELL_SIMPLE) += parser.o obj-$(CONFIG_GREGORIAN_CALENDER) += date.o diff --git a/common/binfmt.c b/common/binfmt.c new file mode 100644 index 0000000000..7dcf5d737d --- /dev/null +++ b/common/binfmt.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * GPL v2 + */ + +#include <common.h> +#include <binfmt.h> +#include <libbb.h> +#include <malloc.h> +#include <command.h> +#include <errno.h> + +static LIST_HEAD(binfmt_hooks); + +static int binfmt_run(char *file, int argc, char **argv) +{ + struct binfmt_hook *b; + enum filetype type = file_name_detect_type(file); + int ret; + + list_for_each_entry(b, &binfmt_hooks, list) { + if (b->type != type) + continue; + + ret = b->hook(b, file, argc, argv); + if (ret != -ERESTARTNOHAND) + return ret; + } + return -ENOENT; +} + +/* + * This converts the original '/executable <args>' into + * 'barebox_cmd <args> /executable' + */ +static int binfmt_exec_excute(struct binfmt_hook *b, char *file, int argc, char **argv) +{ + char **newargv = xzalloc(sizeof(char*) * (argc + 1)); + int ret, i; + + newargv[0] = b->exec; + + for (i = 1 ; i < argc; i++) + newargv[i] = argv[i]; + newargv[i] = file; + + ret = execute_binfmt(argc + 1, newargv); + + free(newargv); + + return ret; +} + +int execute_binfmt(int argc, char **argv) +{ + int ret; + char *path; + + if (strchr(argv[0], '/')) + return binfmt_run(argv[0], argc, argv); + + path = find_execable(argv[0]); + if (path) { + ret = binfmt_run(path, argc, argv); + free(path); + return ret; + } + + return execute_command(argc, &argv[0]); +} + +int binfmt_register(struct binfmt_hook *b) +{ + if (!b || !b->type) + return -EIO; + + if (!b->hook && !b->exec) + return -EIO; + + if (b->exec) + b->hook = binfmt_exec_excute; + + list_add_tail(&b->list, &binfmt_hooks); + + return 0; +} + +void binfmt_unregister(struct binfmt_hook *b) +{ + if (!b) + return; + + list_del(&b->list); +} diff --git a/common/filetype.c b/common/filetype.c index 0120913a56..15a37325df 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -38,6 +38,7 @@ static const char *filetype_str[] = { [filetype_bzip2] = "bzip2 compressed", [filetype_oftree] = "open firmware flat device tree", [filetype_aimage] = "Android boot image", + [filetype_sh] = "Bourne Shell", }; const char *file_type_to_string(enum filetype f) @@ -53,6 +54,8 @@ enum filetype file_detect_type(void *_buf) u32 *buf = _buf; u8 *buf8 = _buf; + if (strncmp(buf8, "#!/bin/sh", 9) == 0) + return filetype_sh; if (buf[8] == 0x65726162 && buf[9] == 0x00786f62) return filetype_arm_barebox; if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01) diff --git a/common/hush.c b/common/hush.c index 053d9a583e..2d89f2b3f2 100644 --- a/common/hush.c +++ b/common/hush.c @@ -124,6 +124,8 @@ #include <libbb.h> #include <magicvar.h> #include <linux/list.h> +#include <binfmt.h> +#include <init.h> /*cmd_boot.c*/ extern int do_bootd(int flag, int argc, char *argv[]); /* do_bootd */ @@ -572,8 +574,6 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi) int nextin; struct child_prog *child; char *p; - char *path; - int ret; # if __GNUC__ /* Avoid longjmp clobbering */ (void) &i; @@ -642,16 +642,7 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi) if (!strcmp(child->argv[i], "getopt")) return builtin_getopt(ctx, child); #endif - if (strchr(child->argv[i], '/')) { - return execute_script(child->argv[i], child->argc-i, &child->argv[i]); - } - if ((path = find_execable(child->argv[i]))) { - ret = execute_script(path, child->argc-i, &child->argv[i]); - free(path); - return ret; - } - - return execute_command(child->argc - i, &child->argv[i]); + return execute_binfmt(child->argc - i, &child->argv[i]); } return -1; } @@ -1749,6 +1740,22 @@ BAREBOX_MAGICVAR(PATH, "colon seperated list of pathes to search for executables BAREBOX_MAGICVAR(PS1, "hush prompt"); #endif +static int binfmt_sh_excute(struct binfmt_hook *b, char *file, int argc, char **argv) +{ + return execute_script(file, argc, argv); +} + +static struct binfmt_hook binfmt_sh_hook = { + .type = filetype_sh, + .hook = binfmt_sh_excute, +}; + +static int binfmt_sh_init(void) +{ + return binfmt_register(&binfmt_sh_hook); +} +fs_initcall(binfmt_sh_init); + /** * @file * @brief A prototype Bourne shell grammar parser diff --git a/defaultenv/bin/boot b/defaultenv/bin/boot index b54ea6b71c..61b893a724 100644 --- a/defaultenv/bin/boot +++ b/defaultenv/bin/boot @@ -134,4 +134,8 @@ fi echo "booting kernel from $kdev" +#try to execute the file +# it does not work as example for /dev as the file is not executable +$kdev $bootm_opt +# fall back on bootm bootm $bootm_opt $kdev diff --git a/include/binfmt.h b/include/binfmt.h new file mode 100644 index 0000000000..46b627e36d --- /dev/null +++ b/include/binfmt.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * GPL v2 + */ + +#ifndef __BFMT_H__ +#define __BFMT_H__ + +#include <filetype.h> +#include <linux/list.h> + +struct binfmt_hook { + enum filetype type; + int (*hook)(struct binfmt_hook *b, char *file, int argc, char **argv); + char *exec; + + struct list_head list; +}; + +#ifdef CONFIG_BINFMT +int binfmt_register(struct binfmt_hook *b); +void binfmt_unregister(struct binfmt_hook *b); + +int execute_binfmt(int argc, char **argv); +#else +static inline int binfmt_register(struct binfmt_hook *b) +{ + return -EINVAL; +} +static inline void binfmt_unregister(struct binfmt_hook *b) {} + +static inline int execute_binfmt(int argc, char **argv) +{ + return 1; +} +#endif + +#endif /* __BFMT_H__ */ diff --git a/include/filetype.h b/include/filetype.h index d0b62265b0..93387938be 100644 --- a/include/filetype.h +++ b/include/filetype.h @@ -16,6 +16,7 @@ enum filetype { filetype_bzip2, filetype_oftree, filetype_aimage, + filetype_sh, }; const char *file_type_to_string(enum filetype f); |