[PATCH 04/20] Introduce application (app) support

Jean-Christophe PLAGNIOL-VILLARD plagnioj at jcrosoft.com
Wed Mar 6 04:29:33 EST 2013


Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
---
 Makefile                    |   47 ++++-
 apps/Kconfig                |   21 +++
 apps/Makefile               |   19 ++
 apps/include/appinfo.h      |   58 ++++++
 arch/arm/Kconfig            |    1 +
 commands/Kconfig            |    7 +
 commands/Makefile           |    1 +
 commands/appinfo.c          |  119 +++++++++++++
 common/Kconfig              |    3 +
 include/apps/syscall_init.h |   23 +++
 include/apps/syscalls.h     |   76 ++++++++
 include/apps/types.h        |   24 +++
 include/linux/license.h     |   14 ++
 lib/Makefile                |    1 +
 lib/apps/Makefile           |    1 +
 lib/apps/syscalls.c         |  413 +++++++++++++++++++++++++++++++++++++++++++
 16 files changed, 825 insertions(+), 3 deletions(-)
 create mode 100644 apps/Kconfig
 create mode 100644 apps/Makefile
 create mode 100644 apps/include/appinfo.h
 create mode 100644 commands/appinfo.c
 create mode 100644 include/apps/syscall_init.h
 create mode 100644 include/apps/syscalls.h
 create mode 100644 include/apps/types.h
 create mode 100644 include/linux/license.h
 create mode 100644 lib/apps/Makefile
 create mode 100644 lib/apps/syscalls.c

diff --git a/Makefile b/Makefile
index 110f7aa..706a1d4 100644
--- a/Makefile
+++ b/Makefile
@@ -297,6 +297,18 @@ LINUXINCLUDE    := -Iinclude \
                    -include include/generated/autoconf.h \
                    -include $(srctree)/include/linux/kconfig.h
 
+# Use APPINCLUDE when you must reference the include/ directory.
+# Needed to be compatible with the O= option
+APPINCLUDE    := -Iapps/include \
+                   $(if $(KBUILD_SRC), -I$(srctree)/apps/include) \
+                   $(if $(KBUILD_SRC), -I$(objtree)/include) \
+		   -I$(srctree)/arch/$(ARCH)/include \
+		   -I$(objtree)/arch/$(ARCH)/include \
+		   -I$(srctree)/arch/$(ARCH)/apps/include \
+		   -I$(objtree)/apps/include \
+                   -include include/generated/autoconf.h \
+                   -include $(srctree)/include/linux/kconfig.h
+
 CPPFLAGS        := -D__KERNEL__ -D__BAREBOX__ -fno-builtin -ffreestanding
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
@@ -315,9 +327,10 @@ export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
 export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
 export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
-export AFLAGS_LINUXINCLUDE
+export APPINCLUDE AFLAGS_LINUXINCLUDE
 export CFLAGS CFLAGS_KERNEL
 export AFLAGS AFLAGS_KERNEL
+export APP_LDFLAGS
 
 # Files to ignore in find ... statements
 
@@ -482,7 +495,18 @@ export KBUILD_BINARY ?= barebox.bin
 barebox-flash-image: $(KBUILD_IMAGE) FORCE
 	$(call if_changed,ln)
 
-all: barebox-flash-image
+ifdef CONFIG_APPLICATIONS
+apps-lds    := $(apps-lds-y)
+export apps-lds
+
+apps := apps
+application: barebox-flash-image
+	$(Q)$(MAKE) $(build)=$(apps) $(apps)/$@
+
+APPS-y += application
+endif
+
+all: barebox-flash-image $(APPS-y)
 
 common-$(CONFIG_PBL_IMAGE)	+= pbl/
 
@@ -493,7 +517,7 @@ barebox-alldirs	:= $(sort $(barebox-dirs) $(patsubst %/,%,$(filter %/, \
 		     $(core-n) $(core-) $(drivers-n) $(drivers-) \
 		     $(net-n)  $(net-)  $(libs-n)    $(libs-))))
 
-app-common-y	:= $(patsubst %/, %/built-in-app.o, $(common-y))
+app-common-y	:= $(patsubst %/, %/built-in-app.o, $(common-y) apps/)
 pbl-common-y	:= $(patsubst %/, %/built-in-pbl.o, $(common-y))
 common-y	:= $(patsubst %/, %/built-in.o, $(common-y))
 
@@ -840,6 +864,23 @@ ifneq ($(KBUILD_SRC),)
 		/bin/false; \
 	fi;
 	$(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
+	$(Q)if [ ! -d apps/include ]; then mkdir -p apps/include; fi;
+	$(Q)if [ ! -d apps/include/barebox ]; then mkdir -p apps/include/barebox; fi;
+	$(Q)if [ ! -h apps/include/linux ]; then  \
+	    ln -fsn $(srctree)/include/linux apps/include/linux;     \
+	    fi;
+	$(Q)if [ ! -h apps/include/asm-generic ]; then  \
+	    ln -fsn $(srctree)/include/asm-generic apps/include/asm-generic;     \
+	    fi;
+	$(Q)if [ ! -h apps/include/generated ]; then  \
+	    ln -fsn $(objtree)/include/generated apps/include/generated;     \
+	    fi;
+	$(Q)if [ ! -e apps/include/barebox/fcntl.h ]; then  \
+	    ln -fsn $(srctree)/include/fcntl.h apps/include/barebox/fcntl.h;     \
+	    fi;
+	$(Q)if [ ! -e apps/include/barebox/types.h ]; then  \
+	    ln -fsn $(srctree)/include/apps/types.h apps/include/barebox/types.h;     \
+	    fi;
 	$(Q)if [ -e $(srctree)/include/asm-$(SRCARCH)/barebox.h ]; then  \
 	    ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm;     \
 	    fi
diff --git a/apps/Kconfig b/apps/Kconfig
new file mode 100644
index 0000000..92899b5
--- /dev/null
+++ b/apps/Kconfig
@@ -0,0 +1,21 @@
+menuconfig APPLICATIONS
+	bool "Applications"
+	depends on HAS_APPLICATIONS
+	depends on EXPERIMENTAL
+	help
+	  This option enables support for running applications.
+
+if APPLICATIONS
+
+menu "memory layout"
+
+source "arch/$SRCARCH/apps/Kconfig"
+
+config APP_MALLOC_SIZE
+	hex
+	default 0x400000
+	prompt "malloc area size"
+
+endmenu
+
+endif
diff --git a/apps/Makefile b/apps/Makefile
new file mode 100644
index 0000000..65adfdc
--- /dev/null
+++ b/apps/Makefile
@@ -0,0 +1,19 @@
+
+CPPFLAGS += -I$(srctree)/apps/include
+
+$(obj)/application: $(apps-lds) $(apps-y)
+
+APP_CPPFLAGS		+= -fdata-sections -ffunction-sections
+
+$(obj)/include/types.h: $(srctree)/include/types.h
+	$(call cmd,shipped)
+
+$(obj)/include/barebox/syscalls.h: $(srctree)/include/apps/syscalls.h
+	$(call cmd,shipped)
+
+$(obj)/include/errno.h: $(srctree)/include/asm-generic/errno.h
+	$(call cmd,shipped)
+
+barebox-app-header += $(obj)/include/types.h
+barebox-app-header += $(obj)/include/errno.h
+barebox-app-header += $(obj)/include/barebox/syscalls.h
diff --git a/apps/include/appinfo.h b/apps/include/appinfo.h
new file mode 100644
index 0000000..94409d7
--- /dev/null
+++ b/apps/include/appinfo.h
@@ -0,0 +1,58 @@
+#ifndef __APPINFO_H__
+#define __APPINFO_H__
+
+/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
+#define ___PASTE(a,b) a##b
+#define __PASTE(a,b) ___PASTE(a,b)
+
+# define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
+
+#define __APP_INFO(tag, name, info)	\
+ static const char __UNIQUE_ID(name)[] \
+ __attribute__((__used__))\
+ __attribute__((section(".appinfo"), unused, aligned(1))) = \
+ #tag "=" info;
+
+/* Generic info of form tag = "info" */
+#define APP_INFO(tag, info)	__APP_INFO(tag, tag, info)
+
+/*
+ * The following license idents are currently accepted as indicating free
+ * software applications
+*
+ *      "GPL"                           [GNU Public License v2 or later]
+ *      "GPL v2"                        [GNU Public License v2]
+ *      "GPL and additional rights"     [GNU Public License v2 rights and more]
+ *      "Dual BSD/GPL"                  [GNU Public License v2
+ *                                       or BSD license choice]
+ *      "Dual MIT/GPL"                  [GNU Public License v2
+ *                                       or MIT license choice]
+ *      "Dual MPL/GPL"                  [GNU Public License v2
+ *                                       or Mozilla license choice]
+ *
+ * The following other idents are available
+ *
+ *      "Proprietary"                   [Non free products]
+ *
+ * There are dual licensed components, but when running with Linux it is
+ * GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
+ * is a GPL combined work.
+ *
+ * This exists for several reasons
+ * 1.   So appinfo can show license info for users wanting to vet their setup 
+ *      is free
+ * 2.   So the community can ignore bug reports including proprietary applications
+ * 3.   So vendors can do likewise based on their own policies
+ */
+
+#define APP_LICENSE(_license)	APP_INFO(license, _license)
+/*
+ * Author(s), use "Name <email>" or just "Name", for multiple
+ * authors use multiple MODULE_AUTHOR() statements/lines.
+ */
+#define APP_AUTHOR(_author)	APP_INFO(author, _author)
+
+/* What your application does. */
+#define APP_DESCRIPTION(_description) APP_INFO(description, _description)
+
+#endif /* __APPINFO_H__ */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7ac134e..f25dcf7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -236,3 +236,4 @@ source drivers/Kconfig
 source fs/Kconfig
 source lib/Kconfig
 source crypto/Kconfig
+source apps/Kconfig
diff --git a/commands/Kconfig b/commands/Kconfig
index c1454c7..b10a8c1 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -242,6 +242,13 @@ config CMD_FILETYPE
 	select FILETYPE
 	prompt "filetype"
 
+config CMD_APPINFO
+	tristate
+	depends on APPLICATIONS
+	prompt "appinfo"
+	help
+	  dump barebox applicaion info
+
 endmenu
 
 menu "console"
diff --git a/commands/Makefile b/commands/Makefile
index 0ae6b95..b9280eb 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_CMD_APPINFO)	+= appinfo.o
 obj-$(CONFIG_STDDEV)		+= stddev.o
 obj-$(CONFIG_CMD_BOOTM)		+= bootm.o
 obj-$(CONFIG_CMD_UIMAGE)	+= uimage.o
diff --git a/commands/appinfo.c b/commands/appinfo.c
new file mode 100644
index 0000000..9736fce
--- /dev/null
+++ b/commands/appinfo.c
@@ -0,0 +1,119 @@
+/*
+ *
+ * Copyright (c) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <errno.h>
+
+/*
+ * first search for #info and then we get the section size
+ * the #info is within the first 512 bytes of the file if present
+ */
+
+#define FILE_APP_BUF 512
+
+static int dump_apping(int fd, int offset, int size)
+{
+	char *buf, *tmp;
+	int ret;
+
+	tmp = buf = xzalloc(size);
+
+	ret = lseek(fd, offset, SEEK_SET);
+	if (ret < 0) {
+		perror("lseek");
+		goto err_out;
+	}
+
+	ret = read(fd, buf, size);
+	if (ret < 0) {
+		perror("read");
+		goto err_out;
+	}
+
+	for (; tmp < buf + size || !strcmp(tmp, "appinf#");
+			tmp += strlen(tmp) + 1) {
+		if (tstc())
+			break;
+		if (strlen(tmp) == 0)
+			break;
+		printf("%s\n", tmp);
+	}
+
+	ret = 0;
+
+err_out:
+	free(buf);
+
+	return ret;
+}
+
+static int do_appinfo(int argc, char *argv[])
+{
+	int fd;
+	char *buf, *tmp;
+	int ret = 1;
+
+	if (argc == 1)
+		return COMMAND_ERROR_USAGE;
+
+	fd = open(argv[1], O_RDONLY);
+
+	if (fd < 0) {
+		perror("open");
+		return fd;
+	}
+
+	tmp = buf = xzalloc(FILE_APP_BUF);
+
+	ret = read(fd, buf, FILE_APP_BUF);
+	if (ret < 0) {
+		perror("read");
+		goto err_out;
+	}
+
+	for (; ret-- ; ++tmp) {
+		if (*tmp != '#')
+			continue;
+
+		if (ret < 8)
+			goto no_app_info;
+
+		if (!strcmp(tmp, "#appinf")) {
+			int size = *((uint32_t*)(tmp + 8));
+			int offset = tmp - buf;
+
+			free(buf);
+			ret = dump_apping(fd, offset + 12, size);
+			goto out;
+		}
+	}
+
+no_app_info:
+	printf("no appinfo found\n");
+
+	ret = 0;
+err_out:
+	free(buf);
+out:
+	close(fd);
+
+	return ret;
+}
+
+BAREBOX_CMD_HELP_START(appinfo)
+BAREBOX_CMD_HELP_USAGE("appinfo <file>\n")
+BAREBOX_CMD_HELP_SHORT("display the barebox application information\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(appinfo)
+	.cmd		= do_appinfo,
+	.usage		= "display the barebox application informatio",
+	BAREBOX_CMD_HELP(cmd_appinfo_help)
+BAREBOX_CMD_END
diff --git a/common/Kconfig b/common/Kconfig
index 3a55e01..6defdbe 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -21,6 +21,9 @@ config HAS_KALLSYMS
 config HAS_MODULES
 	bool
 
+config HAS_APPLICATIONS
+	bool
+
 config CMD_MEMORY
 	bool
 
diff --git a/include/apps/syscall_init.h b/include/apps/syscall_init.h
new file mode 100644
index 0000000..4c496ef
--- /dev/null
+++ b/include/apps/syscall_init.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio at jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __APPS_SYSCALL_INIT_H__
+#define __APPS_SYSCALL_INIT_H__
+
+#include <types.h>
+
+struct syscall_trace {
+	struct list_head dirs;
+	struct list_head fds;
+	void *dest;
+	uint64_t malloc_base;
+	uint32_t malloc_size;
+};
+
+void syscalls_init(struct syscall_trace *t);
+void syscalls_exit(struct syscall_trace *t);
+
+#endif /* __APPS_SYSCALL_INIT_H__ */
diff --git a/include/apps/syscalls.h b/include/apps/syscalls.h
new file mode 100644
index 0000000..e3b10a8
--- /dev/null
+++ b/include/apps/syscalls.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio at jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __APPS_SYSCALLS_H__
+#define __APPS_SYSCALLS_H__
+
+#include <types.h>
+#include <stdarg.h>
+
+#define SYSCALLS_MAGIC "bsyscall"
+
+#define SYS_putchar		0
+#define SYS_getchar		1
+#define SYS_eputc		2
+#define SYS_tstc		3
+
+/* file */
+#define SYS_open		4
+#define SYS_close		5
+#define SYS_read		6
+#define SYS_write		7
+#define SYS_unlink		8
+#define SYS_stat		9
+#define SYS_lstat		10
+#define SYS_lseek		11
+
+/* dir */
+#define SYS_mkdir		12
+#define SYS_rmdir		13
+#define SYS_getcwd		14
+#define SYS_chdir		15
+#define SYS_opendir		16
+#define SYS_readdir		17
+#define SYS_closedir		18
+
+/* symlink */
+#define SYS_symlink		19
+#define SYS_readlink		20
+
+/* mount */
+#define SYS_mount		21
+#define SYS_umount		22
+
+/* device */
+#define SYS_ioctl		23
+
+/* env */
+#define SYS_getenv		24
+#define SYS_setenv		25
+
+/* time */
+#define SYS_ndelay		26
+
+/* exec */
+#define SYS_system		27
+
+/* barebox */
+#define SYS_memmap		100
+
+#ifndef __ASSEMBLY__
+
+struct syscalls_header {
+	char			magic[8];
+	uint32_t		major;
+	uint32_t		minor;
+	uint64_t		malloc_base;
+	uint32_t		malloc_size;
+	uint32_t		nb_syscalls;
+	void			*syscalls;
+};
+#endif
+
+#endif /* __APPS_SYSCALLS_H__ */
diff --git a/include/apps/types.h b/include/apps/types.h
new file mode 100644
index 0000000..2bb6ee6
--- /dev/null
+++ b/include/apps/types.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio at jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#ifndef __APPS_TYPES_H__
+#define __APPS_TYPES_H__
+
+#ifndef __APP__
+#define APP_TYPE_(x) APP_##x
+#else
+#define APP_TYPE_(x) x
+#endif
+
+struct APP_TYPE_(dirent) {
+	char d_name[256];
+};
+
+typedef struct APP_TYPE_(dir) {
+	struct APP_TYPE_(dirent) d;
+} APP_TYPE_(DIR);
+
+#endif /* __APPS_TYPES_H__ */
diff --git a/include/linux/license.h b/include/linux/license.h
new file mode 100644
index 0000000..decdbf4
--- /dev/null
+++ b/include/linux/license.h
@@ -0,0 +1,14 @@
+#ifndef __LICENSE_H
+#define __LICENSE_H
+
+static inline int license_is_gpl_compatible(const char *license)
+{
+	return (strcmp(license, "GPL") == 0
+		|| strcmp(license, "GPL v2") == 0
+		|| strcmp(license, "GPL and additional rights") == 0
+		|| strcmp(license, "Dual BSD/GPL") == 0
+		|| strcmp(license, "Dual MIT/GPL") == 0
+		|| strcmp(license, "Dual MPL/GPL") == 0);
+}
+
+#endif
diff --git a/lib/Makefile b/lib/Makefile
index 3c94542..731bc5b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_LIBMTD)	+= libmtd.o
 obj-y			+= gui/
 obj-$(CONFIG_XYMODEM)	+= xymodem.o
 obj-y			+= unlink-recursive.o
+obj-$(CONFIG_APPLICATIONS)	+= apps/
diff --git a/lib/apps/Makefile b/lib/apps/Makefile
new file mode 100644
index 0000000..86e7071
--- /dev/null
+++ b/lib/apps/Makefile
@@ -0,0 +1 @@
+obj-y += syscalls.o
diff --git a/lib/apps/syscalls.c b/lib/apps/syscalls.c
new file mode 100644
index 0000000..832ba02
--- /dev/null
+++ b/lib/apps/syscalls.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio at jcrosoft.com>
+ *
+ * Under GPLv2 only
+*/
+
+#include <common.h>
+#include <fs.h>
+#include <apps/syscalls.h>
+#include <apps/syscall_init.h>
+#include <apps/types.h>
+#include <linux/stat.h>
+#include <environment.h>
+#include <malloc.h>
+#include <clock.h>
+
+static struct syscall_trace *st_current;
+/* 
+ * keep traking of what is open to close it
+ * when returning
+ */
+struct app_dir_opendir {
+	DIR *d;
+	APP_TYPE_(DIR) *app_d;
+	struct list_head list;
+};
+
+struct app_fd_open {
+	int fd;
+	struct list_head list;
+};
+
+static long sys_putchar(char c)
+{
+	putchar(c);
+
+	return 0;
+}
+
+static long sys_getchar(void)
+{
+	return getc();
+}
+
+static long sys_eputc(char c)
+{
+	eputc(c);
+
+	return 0;
+}
+
+static long sys_tstc(void)
+{
+	return tstc();
+}
+
+static struct app_fd_open *sys_get_file(int fd)
+{
+	struct app_fd_open *af;
+
+	list_for_each_entry(af, &(st_current->fds), list) {
+		if (af->fd == fd)
+			return af;
+	}
+
+	return NULL;
+}
+
+/* barebox does not handle the last optionnal arg */
+static long sys_open(const char *filename, int flags, mode_t mode)
+{
+	struct app_fd_open *af;
+	int fd;
+
+	af = calloc(1, sizeof(*af));
+	if (!af)
+		return -ENOMEM;
+
+	fd = open(filename, flags, mode);
+	if (fd < 3) {
+		free(af);
+	} else {
+		af->fd = fd;
+		list_add_tail(&af->list, &st_current->fds);
+	}
+
+	return fd;
+}
+
+static long sys_close(unsigned int fd)
+{
+	struct app_fd_open *af;
+
+	if (fd > 2) {
+		af = sys_get_file(fd);
+		if (!af)
+			return -EINVAL;
+
+		list_del(&af->list);
+	}
+
+	return close(fd);
+}
+
+static long sys_read(unsigned int fd, char *buf, size_t count)
+{
+	return read(fd, buf, count);
+}
+
+static long sys_write(unsigned int fd, char *buf, size_t count)
+{
+	return write(fd, buf, count);
+}
+
+static long sys_unlink(const char *name)
+{
+	return unlink(name);
+}
+
+static long sys_stat(const char *name, struct stat *s)
+{
+	return lstat(name, s);
+}
+
+static long sys_lstat(const char *name, struct stat *s)
+{
+	return lstat(name, s);
+}
+
+static loff_t sys_lseek(int fd, loff_t offset, int whence)
+{
+	return lseek(fd, offset, whence);
+}
+
+static long sys_mkdir(char *name, mode_t mode)
+{
+	return mkdir(name, mode);
+}
+
+static long sys_rmdir(char *name)
+{
+	return rmdir(name);
+}
+
+/* int getcwd(char* buf, size_t size) */
+static long sys_getcwd(char* buf, size_t size)
+{
+	const char *path;
+	int len;
+
+	if (!buf)
+		return -ENOMEM;
+
+	path = getcwd();
+	len = strlen(path);
+
+	strncpy(buf, path, min(len, (int)size));
+
+	return 0;
+}
+
+static long sys_chdir(char *name)
+{
+	return chdir(name);
+}
+
+static struct app_dir_opendir *sys_get_dir(APP_TYPE_(DIR) *d)
+{
+	struct app_dir_opendir *ad;
+
+	list_for_each_entry(ad, &st_current->dirs, list) {
+		if (ad->app_d == d)
+			return ad;
+	}
+
+	return NULL;
+}
+
+/*
+ * int opendir(DIR *, char *name)
+ *
+ * Do not expose barebox internal struct
+ */
+static long sys_opendir(APP_TYPE_(DIR) *dir, const char *name)
+{
+	DIR *d;
+	struct app_dir_opendir *ad;
+	int ret;
+
+	ad = calloc(1, sizeof(*ad));
+	if (!ad)
+		return -ENOMEM;
+
+
+	d = opendir(name);
+	if (!d) {
+		ret = -ENOENT;
+		goto err;
+	}
+
+	strcpy(dir->d.d_name, d->d.d_name);
+
+	ad->app_d = dir;
+	ad->d = d;
+
+	list_add_tail(&ad->list, &st_current->dirs);
+
+	return 0;
+
+err:
+	free(ad);
+	return ret;
+}
+
+static long sys_readdir(APP_TYPE_(DIR) *app_dir, struct APP_TYPE_(dirent) *app_d)
+{
+	struct app_dir_opendir *ad;
+	struct dirent *d;
+
+	ad = sys_get_dir(app_dir);
+	if (!ad) {
+		app_d = NULL;
+		return -EINVAL;
+	}
+
+	d = readdir(ad->d);
+
+	if (!d || !d->d_name) {
+		app_d = NULL;
+		return -ENOENT;
+	}
+
+	strcpy(app_d->d_name, d->d_name);
+
+	return 0;
+}
+
+static long sys_closedir(APP_TYPE_(DIR) *app_dir)
+{
+	struct app_dir_opendir *ad;
+	int ret;
+
+	ad = sys_get_dir(app_dir);
+	if (!ad)
+		return -EINVAL;
+
+	ret = closedir(ad->d);
+
+	list_del(&ad->list);
+
+	return ret;
+}
+
+static long sys_symlink(const char *src, const char *dest)
+{
+	return symlink(src, dest);
+}
+
+static long sys_readlink(const char * path, char * buf, u32 bufsiz)
+{
+	return readlink(path, buf, bufsiz);
+}
+
+/*
+ * libc mount
+ * int mount(const char *source, const char *target,
+ *           const char *fstype, unsigned long mountflags,
+ *	     const void *data);
+ * barebox
+ * int mount(const char *device, const char *fsname, const char *_path)
+ */
+static long sys_mount(char *dev_name, char *dir_name,
+		char *type, unsigned long flags,
+		void *data)
+{
+	return mount(dev_name, type, dir_name);
+}
+
+static long sys_umount(char *name, int flags)
+{
+	return umount(name);
+}
+
+static long sys_ioctl(unsigned int fd, unsigned int cmd,
+				unsigned long arg)
+{
+	return ioctl(fd, cmd, (void*)arg);
+}
+
+static long sys_getenv(char *value, const char *name)
+{
+	strcpy(value, getenv(name));
+
+	return 0;
+}
+
+static long sys_setenv(const char *name, const char *value)
+{
+	return setenv(name, value);
+}
+
+static long sys_ndelay(unsigned long nsecs)
+{
+	uint64_t start = get_time_ns();
+
+	while(!is_timeout(start, nsecs));
+
+	return 0;
+}
+
+static long sys_nil(unsigned long arg0, unsigned long arg1, unsigned long arg2)
+{
+	pr_err("%s(0x%lx, 0x%lx, 0x%lx)\n", __func__, arg0, arg1, arg2);
+	return -ENOSYS;
+}
+
+#define __SYSCALL(name) [SYS_##name] = sys_##name
+
+static void *sys_funcs[] = {
+	__SYSCALL(putchar),
+	__SYSCALL(getchar),
+	__SYSCALL(eputc),
+	__SYSCALL(tstc),
+	/* file */
+	__SYSCALL(open),
+	__SYSCALL(close),
+	__SYSCALL(read),
+	__SYSCALL(write),
+	__SYSCALL(unlink),
+	__SYSCALL(stat),
+	__SYSCALL(lstat),
+	__SYSCALL(lseek),
+	/* dir */
+	__SYSCALL(mkdir),
+	__SYSCALL(rmdir),
+	__SYSCALL(getcwd),
+	__SYSCALL(chdir),
+	__SYSCALL(opendir),
+	__SYSCALL(readdir),
+	__SYSCALL(closedir),
+	/* symlink */
+	__SYSCALL(symlink),
+	__SYSCALL(readlink),
+	/* mount */
+	__SYSCALL(mount),
+	__SYSCALL(umount),
+	/* device */
+	__SYSCALL(ioctl),
+	/* env */
+	__SYSCALL(getenv),
+	__SYSCALL(setenv),
+	/* env */
+	__SYSCALL(ndelay),
+};
+
+struct syscalls_header syscalls = {
+	.magic = SYSCALLS_MAGIC,
+	.major = 1,
+	.minor = 0,
+	.nb_syscalls = ARRAY_SIZE(sys_funcs),
+	.syscalls = sys_funcs,
+};
+
+void syscalls_init(struct syscall_trace *t)
+{
+	struct syscalls_header *app_syscalls = t->dest;
+	int size = sizeof(syscalls);
+	void **dest;
+	int i;
+
+	pr_debug("t->dest = 0x%p\n", t->dest);
+
+	pr_debug("sizeof = %d\n", size);
+	memcpy(t->dest, &syscalls, sizeof(syscalls));
+
+	app_syscalls->malloc_base = t->malloc_base;
+	app_syscalls->malloc_size = t->malloc_size;
+	dest = t->dest + size;
+
+	size = sizeof(void*) * syscalls.nb_syscalls;
+	pr_debug("dest = 0x%p\n", dest);
+	pr_debug("size = %d\n", size);
+
+	app_syscalls->syscalls = dest;
+	memcpy(dest, sys_funcs, size);
+
+	for (i = 0; i < syscalls.nb_syscalls; i++) {
+		if (!dest[i]) {
+			pr_debug("syscall %d not implemented\n", i);
+			dest[i] = sys_nil;
+		}
+	}
+
+	INIT_LIST_HEAD(&t->dirs);
+	INIT_LIST_HEAD(&t->fds);
+}
+
+void syscalls_exit(struct syscall_trace *t)
+{
+	struct app_dir_opendir *ad, *tmpd;
+	struct app_fd_open *af, *tmpf;
+
+	list_for_each_entry_safe(ad, tmpd, &t->dirs, list) {
+		closedir(ad->d);
+		list_del(&ad->list);
+	}
+
+	list_for_each_entry_safe(af, tmpf, &t->fds, list) {
+		close(af->fd);
+		list_del(&af->list);
+	}
+}
+
-- 
1.7.10.4




More information about the barebox mailing list