summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2012-04-18 20:42:17 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2012-04-18 20:42:17 +0200
commita7ddbc40865a8ffe716aca686763780febad575c (patch)
tree66084fa9f4ac31bff8a3326198d47930f1ccf7b5
parent030b5a1ba5bfb5cbbf8ff88f8880184b5fc76354 (diff)
parent2b26b148f4c8633a19bca0cbb96d4393ece8f54e (diff)
downloadbarebox-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.c22
-rw-r--r--commands/bootm.c12
-rw-r--r--common/Kconfig5
-rw-r--r--common/Makefile1
-rw-r--r--common/binfmt.c95
-rw-r--r--common/filetype.c3
-rw-r--r--common/hush.c31
-rw-r--r--defaultenv/bin/boot4
-rw-r--r--include/binfmt.h39
-rw-r--r--include/filetype.h1
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);