mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH v2] ARM: Add support for semihosting
@ 2015-10-28 18:34 Andrey Smirnov
  2015-10-28 18:34 ` [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start() Andrey Smirnov
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Andrey Smirnov @ 2015-10-28 18:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Add semihosting API implementation and implement a filesystem driver
to access debugging host filesystem using it.

Tested on Freescale SabreSD board (i.MX6Q) using OpenOCD

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---

New in version 2:

 - Added documntation for host side setup needed (including no MMU limitation for OpenOCD)
 - Fixed a small bug, where errno values were not negated
 - Fixed compilation errors of the previous patch


 Documentation/filesystems/smhfs.rst |  57 +++++++++
 arch/arm/Kconfig                    |   9 ++
 arch/arm/include/asm/semihosting.h  |  19 +++
 arch/arm/lib/Makefile               |   1 +
 arch/arm/lib/semihosting-trap.S     |  28 +++++
 arch/arm/lib/semihosting.c          | 227 ++++++++++++++++++++++++++++++++++++
 fs/Kconfig                          |   9 ++
 fs/Makefile                         |   1 +
 fs/smhfs.c                          | 178 ++++++++++++++++++++++++++++
 9 files changed, 529 insertions(+)
 create mode 100644 Documentation/filesystems/smhfs.rst
 create mode 100644 arch/arm/include/asm/semihosting.h
 create mode 100644 arch/arm/lib/semihosting-trap.S
 create mode 100644 arch/arm/lib/semihosting.c
 create mode 100644 fs/smhfs.c

diff --git a/Documentation/filesystems/smhfs.rst b/Documentation/filesystems/smhfs.rst
new file mode 100644
index 0000000..28de146
--- /dev/null
+++ b/Documentation/filesystems/smhfs.rst
@@ -0,0 +1,57 @@
+.. index:: smhfs (filesystem)
+
+.. _filesystems_smhfs:
+
+File I/O over ARM semihosting support
+=====================================
+
+Target Side Setup
+-----------------
+
+barebox can communicate with debug programms attached via SWD/JTAG by
+means of ARM semihosting protocol.
+
+Not all of the I/O primitives neccessary to implement a full
+filesystem are exposed in ARM semihosting API and because of that some
+aspects of filesystem funcionality are missing. Implementation does
+not have support for listing directories. This means a
+:ref:`command_ls` to a SMHFS-mounted path will show an empty
+directory. Nevertheless, the files are there.
+
+Example::
+
+  mount -t smhfs /dev/null /mnt/smhfs
+
+
+Host Side Setup
+---------------
+
+FIXME: Currently OpenOCD does not work correctly if Barebox is built
+with MMU enabled, so before using this featrue, please make sure that
+MMU is disabled in your particular configuration
+
+To make semihosting work host machine connected to the target via
+JTAG/SWD must have semihosting capable debug software running. One
+such tool would be OpenOCD. For ARM9 and ARM11 CPUs most recent
+release of OpenOCD should suffice, however for ARMv7A based devices
+patched version from here http://openocd.zylin.com/#/c/2908/ has to be
+used.
+
+The following steps are required to set up a operational semihosting
+channel:
+
+      1. In a terminal start OpenOCD and specify your particular board
+         and debug adapter used.
+
+      2. In a separate terminal connect to OpenOCD via telnet
+
+	   telnet localhost 4444
+
+      3. In resulting telnet session execute the following commands:
+
+           halt
+	   arm semihosting on
+	   resume
+
+After that is done all of the semihosting related functions should be
+ready to use.
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 304b6e6..1bccca3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -326,6 +326,15 @@ config ARM_UNWIND
 	  the performance is not affected. Currently, this feature
 	  only works with EABI compilers. If unsure say Y.

+config ARM_SEMIHOSTING
+	bool "enable ARM semihosting support"
+	help
+	  This option enables ARM semihosting support in barebox. ARM
+	  semihosting is a communication discipline that allows code
+	  running on target ARM cpu perform system calls and access
+	  the data on the host computer connected to the target via
+	  debugging channel (JTAG, SWD). If unsure say N
+
 endmenu

 source common/Kconfig
diff --git a/arch/arm/include/asm/semihosting.h b/arch/arm/include/asm/semihosting.h
new file mode 100644
index 0000000..b478dad
--- /dev/null
+++ b/arch/arm/include/asm/semihosting.h
@@ -0,0 +1,19 @@
+#ifndef __ASM_ARM_SEMIHOSTING_H
+#define __ASM_ARM_SEMIHOSTING_H
+
+int semihosting_open(const char *fname, int flags);
+int semihosting_close(int fd);
+int semihosting_writec(char c);
+int semihosting_write0(const char *str);
+ssize_t semihosting_write(int fd, const void *buf, size_t count);
+ssize_t semihosting_read(int fd, void *buf, size_t count);
+int semihosting_readc(void);
+int semihosting_isatty(int fd);
+int semihosting_seek(int fd, loff_t pos);
+int semihosting_flen(int fd);
+int semihosting_remove(const char *fname);
+int semihosting_rename(const char *fname1, const char *fname2);
+int semihosting_errno(void);
+int semihosting_system(const char *command);
+
+#endif
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index a328795..e1c6f5b 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -20,6 +20,7 @@ pbl-y	+= runtime-offset.o
 obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS)	+= memcpy.o
 obj-$(CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS)	+= memset.o
 obj-$(CONFIG_ARM_UNWIND) += unwind.o
+obj-$(CONFIG_ARM_SEMIHOSTING) += semihosting-trap.o semihosting.o
 obj-$(CONFIG_MODULES) += module.o
 extra-y += barebox.lds

diff --git a/arch/arm/lib/semihosting-trap.S b/arch/arm/lib/semihosting-trap.S
new file mode 100644
index 0000000..9e40ebf
--- /dev/null
+++ b/arch/arm/lib/semihosting-trap.S
@@ -0,0 +1,28 @@
+/*
+ * semihosting-trap.S -- Assembly code needed to make a semihosting call
+ *
+ * Copyright (c) 2015 Zodiac Inflight Innovations
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 <linux/linkage.h>
+#include <asm/unified.h>
+
+.section .text.semihosting_trap
+ENTRY(semihosting_trap)
+	@ In supervisor mode SVC would clobber LR
+	push	{lr}
+	ARM(	svc	#0x123456	)
+	THUMB(	svc	#0xAB		)
+	pop	{pc}
+ENDPROC(semihosting_trap)
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c
new file mode 100644
index 0000000..a735196
--- /dev/null
+++ b/arch/arm/lib/semihosting.c
@@ -0,0 +1,227 @@
+/*
+ * semihosting.c -- ARM Semihoting API implementation
+ *
+ * Copyright (c) 2015 Zodiac Inflight Innovations
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * based on a smiliar code from U-Boot
+ * Copyright (c) 2014 Broadcom Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 <common.h>
+#include <command.h>
+#include <fcntl.h>
+
+#ifndef O_BINARY
+#define O_BINARY	0
+#endif
+
+
+enum {
+	SEMIHOSTING_SYS_OPEN	= 0x01,
+	SEMIHOSTING_SYS_CLOSE	= 0x02,
+	SEMIHOSTING_SYS_WRITEC	= 0x03,
+	SEMIHOSTING_SYS_WRITE0	= 0x04,
+	SEMIHOSTING_SYS_WRITE	= 0x05,
+	SEMIHOSTING_SYS_READ	= 0x06,
+	SEMIHOSTING_SYS_READC	= 0x07,
+	/* SYS_ISERROR is not implemented  */
+	SEMIHOSTING_SYS_ISATTY	= 0x09,
+	SEMIHOSTING_SYS_SEEK	= 0x0a,
+	SEMIHOSTING_SYS_FLEN	= 0x0c,
+	SEMIHOSTING_SYS_REMOVE	= 0x0e,
+	SEMIHOSTING_SYS_RENAME	= 0x0f,
+	SEMIHOSTING_SYS_TIME	= 0x11,
+	SEMIHOSTING_SYS_ERRNO	= 0x13,
+	/* SYS_GET_CMDLINE is not implemented */
+	/* SYS_HEAPINFO is not implemented */
+	/* angel_SWIreason_ReportException is not implemented */
+	SEMIHOSTING_SYS_SYSTEM	= 0x12,
+};
+
+uint32_t semihosting_trap(uint32_t sysnum, void *addr);
+
+static uint32_t semihosting_flags_to_mode(int flags)
+{
+	static const int semihosting_open_modeflags[12] = {
+		O_RDONLY,
+		O_RDONLY | O_BINARY,
+		O_RDWR,
+		O_RDWR | O_BINARY,
+		O_WRONLY | O_CREAT | O_TRUNC,
+		O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+		O_RDWR | O_CREAT | O_TRUNC,
+		O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
+		O_WRONLY | O_CREAT | O_APPEND,
+		O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
+		O_RDWR | O_CREAT | O_APPEND,
+		O_RDWR | O_CREAT | O_APPEND | O_BINARY
+	};
+
+	int i;
+	for (i = 0; i < ARRAY_SIZE(semihosting_open_modeflags); i++) {
+		if (semihosting_open_modeflags[i] == flags)
+			return i;
+	}
+
+	return 0;
+}
+
+int semihosting_open(const char *fname, int flags)
+{
+	struct __packed {
+		uint32_t fname;
+		uint32_t mode;
+		uint32_t len;
+	} open = {
+		.fname = (uint32_t)fname,
+		.len = strlen(fname),
+		.mode = semihosting_flags_to_mode(flags),
+	};
+
+	return semihosting_trap(SEMIHOSTING_SYS_OPEN, &open);
+}
+EXPORT_SYMBOL(semihosting_open);
+
+int semihosting_close(int fd)
+{
+	return semihosting_trap(SEMIHOSTING_SYS_CLOSE, &fd);
+}
+EXPORT_SYMBOL(semihosting_close);
+
+int semihosting_writec(char c)
+{
+	return semihosting_trap(SEMIHOSTING_SYS_WRITEC, &c);
+}
+EXPORT_SYMBOL(semihosting_writec);
+
+int semihosting_write0(const char *str)
+{
+	return semihosting_trap(SEMIHOSTING_SYS_WRITE0, (void *)str);
+}
+EXPORT_SYMBOL(semihosting_write0);
+
+struct __packed semihosting_file_io {
+	uint32_t fd;
+	uint32_t memp;
+	uint32_t len;
+};
+
+ssize_t semihosting_write(int fd, const void *buf, size_t count)
+{
+	struct semihosting_file_io write = {
+		.fd = fd,
+		.memp = (uint32_t)buf,
+		.len = count,
+	};
+
+	return semihosting_trap(SEMIHOSTING_SYS_WRITE, &write);
+}
+EXPORT_SYMBOL(semihosting_write);
+
+ssize_t semihosting_read(int fd, void *buf, size_t count)
+{
+	struct semihosting_file_io read = {
+		.fd = fd,
+		.memp = (uint32_t)buf,
+		.len = count,
+	};
+
+	return semihosting_trap(SEMIHOSTING_SYS_READ, &read);
+}
+EXPORT_SYMBOL(semihosting_read);
+
+int semihosting_readc(void)
+{
+	return semihosting_trap(SEMIHOSTING_SYS_READC, NULL);
+}
+EXPORT_SYMBOL(semihosting_readc);
+
+int semihosting_isatty(int fd)
+{
+	return semihosting_trap(SEMIHOSTING_SYS_ISATTY, &fd);
+}
+EXPORT_SYMBOL(semihosting_isatty);
+
+int semihosting_seek(int fd, off_t pos)
+{
+	struct __packed {
+		uint32_t fd;
+		uint32_t pos;
+	} seek = {
+		.fd = fd,
+		.pos = pos,
+	};
+
+	return semihosting_trap(SEMIHOSTING_SYS_SEEK, &seek);
+}
+EXPORT_SYMBOL(semihosting_seek);
+
+int semihosting_flen(int fd)
+{
+	return semihosting_trap(SEMIHOSTING_SYS_FLEN, &fd);
+}
+EXPORT_SYMBOL(semihosting_flen);
+
+int semihosting_remove(const char *fname)
+{
+	struct __packed {
+		uint32_t fname;
+		uint32_t fname_length;
+	} remove = {
+		.fname = (uint32_t)fname,
+		.fname_length = strlen(fname),
+	};
+
+	return semihosting_trap(SEMIHOSTING_SYS_REMOVE, &remove);
+}
+EXPORT_SYMBOL(semihosting_remove);
+
+int semihosting_rename(const char *fname1, const char *fname2)
+{
+	struct __packed {
+		uint32_t fname1;
+		uint32_t fname1_length;
+		uint32_t fname2;
+		uint32_t fname2_length;
+	} rename = {
+		.fname1 = (uint32_t)fname1,
+		.fname1_length = strlen(fname1),
+		.fname2 = (uint32_t)fname2,
+		.fname2_length = strlen(fname2),
+	};
+
+	return semihosting_trap(SEMIHOSTING_SYS_RENAME, &rename);
+}
+EXPORT_SYMBOL(semihosting_rename);
+
+int semihosting_errno(void)
+{
+	return semihosting_trap(SEMIHOSTING_SYS_ERRNO, NULL);
+}
+EXPORT_SYMBOL(semihosting_errno);
+
+
+int semihosting_system(const char *command)
+{
+	struct __packed {
+		uint32_t cmd;
+		uint32_t cmd_len;
+	} system = {
+		.cmd = (uint32_t)command,
+		.cmd_len = strlen(command),
+	};
+
+	return semihosting_trap(SEMIHOSTING_SYS_SYSTEM, &system);
+}
+EXPORT_SYMBOL(semihosting_system);
diff --git a/fs/Kconfig b/fs/Kconfig
index feab537..9217bc8 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -80,4 +80,13 @@ config FS_UIMAGEFS
 	select CRC32
 	prompt "uImage FS support"

+config FS_SMHFS
+	depends on ARM_SEMIHOSTING
+	bool
+	prompt "Semihosting FS support"
+	help
+	  If enabled this filesystem provides access to the files
+	  located on a debugging host connected to the target running
+	  Barebox
+
 endmenu
diff --git a/fs/Makefile b/fs/Makefile
index f5aae91..4693205 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_FS_BPKFS) += bpkfs.o
 obj-$(CONFIG_FS_UIMAGEFS)	+= uimagefs.o
 obj-$(CONFIG_FS_EFI)	 += efi.o
 obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o
+obj-$(CONFIG_FS_SMHFS) += smhfs.o
diff --git a/fs/smhfs.c b/fs/smhfs.c
new file mode 100644
index 0000000..a0df06c
--- /dev/null
+++ b/fs/smhfs.c
@@ -0,0 +1,178 @@
+/*
+ * smhfs.c -- Driver implementing pseudo FS interface on top of ARM
+ *            semihosting
+ *
+ * Copyright (c) 2015 Zodiac Inflight Innovations
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 <common.h>
+#include <command.h>
+#include <init.h>
+#include <fs.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <asm/semihosting.h>
+
+static int file_to_fd(const FILE *f)
+{
+	return (int)f->priv;
+}
+
+static int smhfs_create(struct device_d __always_unused *dev,
+			const char __always_unused *pathname,
+			mode_t __always_unused mode)
+{
+	return 0;
+}
+
+static int smhfs_mkdir(struct device_d __always_unused *dev,
+		       const char __always_unused *pathname)
+{
+	return -ENOSYS;
+}
+
+static int smhfs_rm(struct device_d __always_unused *dev,
+		    const char *pathname)
+{
+	/* Get rid of leading '/' */
+	pathname = &pathname[1];
+
+	if (semihosting_remove(pathname) != 0)
+		return -semihosting_errno();
+	else
+		return 0;
+}
+
+static int smhfs_truncate(struct device_d __always_unused *dev,
+			  FILE __always_unused *f,
+			  ulong __always_unused size)
+{
+	return -ENOSYS;
+}
+
+static int smhfs_open(struct device_d __always_unused *dev,
+		      FILE *file, const char *filename)
+{
+	int fd;
+	/* Get rid of leading '/' */
+	filename = &filename[1];
+
+	fd = semihosting_open(filename, file->flags);
+	if (fd < 0)
+		goto error;
+
+	file->priv = (void *)fd;
+	file->size = semihosting_flen(fd);
+	if (file->size < 0)
+		goto error;
+
+	return 0;
+error:
+	return -semihosting_errno();
+}
+
+static int smhfs_close(struct device_d __always_unused *dev,
+		       FILE *f)
+{
+	if (semihosting_close(file_to_fd(f)))
+		return -semihosting_errno();
+	else
+		return 0;
+}
+
+static int smhfs_write(struct device_d __always_unused *dev,
+		       FILE *f, const void *inbuf, size_t insize)
+{
+	if (semihosting_write(file_to_fd(f), inbuf, insize))
+		return -semihosting_errno();
+	else
+		return insize;
+}
+
+static int smhfs_read(struct device_d __always_unused *dev,
+		      FILE *f, void *buf, size_t insize)
+{
+	if (!semihosting_read(file_to_fd(f), buf, insize))
+		return insize;
+	else
+		return -semihosting_errno();
+}
+
+static loff_t smhfs_lseek(struct device_d __always_unused *dev,
+			  FILE *f, loff_t pos)
+{
+	if (semihosting_seek(file_to_fd(f), pos)) {
+		return -semihosting_errno();
+	} else {
+		f->pos = pos;
+		return f->pos;
+	}
+}
+
+static DIR* smhfs_opendir(struct device_d __always_unused *dev,
+			  const char __always_unused *pathname)
+{
+	return NULL;
+}
+
+static int smhfs_stat(struct device_d __always_unused *dev,
+		      const char *filename, struct stat *s)
+{
+	FILE file;
+
+	if (smhfs_open(NULL, &file, filename) == 0) {
+		s->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
+		s->st_size = file.size;
+	}
+	smhfs_close(NULL, &file);
+
+	return 0;
+}
+
+static int smhfs_probe(struct device_d __always_unused *dev)
+{
+	/* TODO: Add provisions to detect if debugger is connected */
+	return 0;
+}
+
+static void smhfs_remove(struct device_d __always_unused *dev)
+{
+}
+
+static struct fs_driver_d smhfs_driver = {
+	.open      = smhfs_open,
+	.close     = smhfs_close,
+	.read      = smhfs_read,
+	.lseek     = smhfs_lseek,
+	.opendir   = smhfs_opendir,
+	.stat      = smhfs_stat,
+	.create    = smhfs_create,
+	.unlink    = smhfs_rm,
+	.mkdir     = smhfs_mkdir,
+	.rmdir     = smhfs_rm,
+	.write     = smhfs_write,
+	.truncate  = smhfs_truncate,
+	.flags     = FS_DRIVER_NO_DEV,
+	.drv = {
+		.probe  = smhfs_probe,
+		.remove = smhfs_remove,
+		.name = "smhfs",
+	}
+};
+
+static int smhfs_init(void)
+{
+	return register_fs_driver(&smhfs_driver);
+}
+coredevice_initcall(smhfs_init);
--
2.1.4

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start().
  2015-10-28 18:34 [PATCH v2] ARM: Add support for semihosting Andrey Smirnov
@ 2015-10-28 18:34 ` Andrey Smirnov
  2015-10-30  7:20   ` Sascha Hauer
  2015-10-28 18:34 ` [PATCH v2 2/2] arm/cpu: Avoid multiple definitions of barebox_arm_entry Andrey Smirnov
  2015-10-30  7:10 ` [PATCH v2] ARM: Add support for semihosting Sascha Hauer
  2 siblings, 1 reply; 6+ messages in thread
From: Andrey Smirnov @ 2015-10-28 18:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

Both barebox_boarddata and barebox_boot_dtb perform essentially the
same function -- hold a pointer to a chunk of private data. Since only
one variable is ever used at any given time we may as well merge those
two variable into one. This also allows us to share more code between
two boot paths (board data vs. device tree)

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---

Changes since v1:
	- Unified barebox_boarddata and barebox_boot_dtb into
          barebox_private_data which allowed to simplify distilled code
          and avoid using double star pointers


 arch/arm/cpu/start.c | 58 +++++++++++++++++++++++++++++++++-------------------
 1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 8e5097b..066dad8 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -32,25 +32,35 @@
 #include "mmu-early.h"

 unsigned long arm_stack_top;
-static void *barebox_boarddata;
+static void *barebox_private_data;

 u32 barebox_arm_machine(void)
 {
 	struct barebox_arm_boarddata *bd;

-	if (!barebox_boarddata)
+	if (!barebox_private_data)
 		return 0;

-	bd = barebox_boarddata;
+	bd = barebox_private_data;

 	return bd->machine;
 }

-static void *barebox_boot_dtb;
-
 void *barebox_arm_boot_dtb(void)
 {
-	return barebox_boot_dtb;
+	return barebox_private_data;
+}
+
+static uint32_t get_any_boarddata_magic(const void *boarddata)
+{
+	if (get_unaligned_be32(boarddata) == FDT_MAGIC)
+		return FDT_MAGIC;
+
+	if (((struct barebox_arm_boarddata *)boarddata)->magic ==
+	    BAREBOX_ARM_BOARDDATA_MAGIC)
+		return BAREBOX_ARM_BOARDDATA_MAGIC;
+
+	return 0;
 }

 static noinline __noreturn void __start(unsigned long membase,
@@ -70,7 +80,6 @@ static noinline __noreturn void __start(unsigned long membase,

 	pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);

-	barebox_boarddata = boarddata;
 	arm_stack_top = endmem;
 	endmem -= STACK_SIZE; /* Stack */

@@ -89,21 +98,28 @@ static noinline __noreturn void __start(unsigned long membase,
 	}

 	if (boarddata) {
-		if (get_unaligned_be32(boarddata) == FDT_MAGIC) {
-			uint32_t totalsize = get_unaligned_be32(boarddata + 4);
+		uint32_t totalsize = 0;
+		const char *name;
+
+		switch (get_any_boarddata_magic(boarddata)) {
+		case FDT_MAGIC:
+			totalsize = get_unaligned_be32(boarddata + 4);
+			name = "DTB";
+			break;
+		case BAREBOX_ARM_BOARDDATA_MAGIC:
+			totalsize = sizeof(struct barebox_arm_boarddata);
+			name = "machine type";
+			break;
+		default:
+			break;
+		}
+
+		if (totalsize) {
 			endmem -= ALIGN(totalsize, 64);
-			barebox_boot_dtb = (void *)endmem;
-			pr_debug("found DTB in boarddata, copying to 0x%p\n",
-					barebox_boot_dtb);
-			memcpy(barebox_boot_dtb, boarddata, totalsize);
-		} else if (((struct barebox_arm_boarddata *)boarddata)->magic ==
-				BAREBOX_ARM_BOARDDATA_MAGIC) {
-			endmem -= ALIGN(sizeof(struct barebox_arm_boarddata), 64);
-			barebox_boarddata = (void *)endmem;
-			pr_debug("found machine type in boarddata, copying to 0x%p\n",
-					barebox_boarddata);
-			memcpy(barebox_boarddata, boarddata,
-					sizeof(struct barebox_arm_boarddata));
+			pr_debug("found %s in boarddata, copying to 0x%lu\n",
+				 name, endmem);
+			barebox_private_data = memcpy((void *)endmem,
+						      boarddata, totalsize);
 		}
 	}

--
2.1.4

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 2/2] arm/cpu: Avoid multiple definitions of barebox_arm_entry
  2015-10-28 18:34 [PATCH v2] ARM: Add support for semihosting Andrey Smirnov
  2015-10-28 18:34 ` [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start() Andrey Smirnov
@ 2015-10-28 18:34 ` Andrey Smirnov
  2015-10-30  7:10 ` [PATCH v2] ARM: Add support for semihosting Sascha Hauer
  2 siblings, 0 replies; 6+ messages in thread
From: Andrey Smirnov @ 2015-10-28 18:34 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov

All versions of barebox_arm_entry (in uncompress.c, start.c and
start-pbl.c) appear to be doing exacty the same thing. So move the
definition into a separate file and use IS_ENABLED macro to avoid
re-definition.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---

Changes since v1:
	- Hopefully more meningfull names for former internal symbols


 arch/arm/cpu/Makefile     |  4 ++--
 arch/arm/cpu/entry.c      | 38 +++++++++++++++++++++++++++++++++++++
 arch/arm/cpu/entry.h      | 48 +++++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/cpu/start-pbl.c  | 29 +---------------------------
 arch/arm/cpu/start.c      | 29 ++--------------------------
 arch/arm/cpu/uncompress.c | 16 +---------------
 6 files changed, 92 insertions(+), 72 deletions(-)
 create mode 100644 arch/arm/cpu/entry.c
 create mode 100644 arch/arm/cpu/entry.h

diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index fb3929c..418bcab 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -1,7 +1,7 @@
 obj-y += cpu.o
 obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions.o
 obj-$(CONFIG_ARM_EXCEPTIONS) += interrupts.o
-obj-y += start.o setupc.o
+obj-y += start.o setupc.o entry.o

 #
 # Any variants can be called as start-armxyz.S
@@ -23,7 +23,7 @@ AFLAGS_pbl-cache-armv7.o       :=-Wa,-march=armv7-a
 pbl-$(CONFIG_CPU_32v7) += cache-armv7.o
 obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o

-pbl-y += setupc.o
+pbl-y += setupc.o entry.o
 pbl-$(CONFIG_PBL_SINGLE_IMAGE) += start-pbl.o
 pbl-$(CONFIG_PBL_MULTI_IMAGES) += uncompress.o

diff --git a/arch/arm/cpu/entry.c b/arch/arm/cpu/entry.c
new file mode 100644
index 0000000..3b74c6a
--- /dev/null
+++ b/arch/arm/cpu/entry.c
@@ -0,0 +1,38 @@
+#include <types.h>
+
+#include <asm/cache.h>
+
+#include "entry.h"
+
+/*
+ * Main ARM entry point. Call this with the memory region you can
+ * spare for barebox. This doesn't necessarily have to be the full
+ * SDRAM. The currently running binary can be inside or outside of
+ * this region. TEXT_BASE can be inside or outside of this
+ * region. boarddata will be preserved and can be accessed later with
+ * barebox_arm_boarddata().
+ *
+ * -> membase + memsize
+ *   STACK_SIZE              - stack
+ *   16KiB, aligned to 16KiB - First level page table if early MMU support
+ *                             is enabled
+ *   128KiB                  - early memory space
+ * -> maximum end of barebox binary
+ *
+ * Usually a TEXT_BASE of 1MiB below your lowest possible end of memory should
+ * be fine.
+ */
+
+void __naked __noreturn barebox_arm_entry(unsigned long membase,
+					  unsigned long memsize, void *boarddata)
+{
+	arm_setup_stack(membase + memsize - 16);
+	arm_early_mmu_cache_invalidate();
+
+	if (IS_ENABLED(CONFIG_PBL_MULTI_IMAGES))
+		barebox_multi_pbl_start(membase, memsize, boarddata);
+	else if (IS_ENABLED(CONFIG_PBL_SINGLE_IMAGE))
+		barebox_single_pbl_start(membase, memsize, boarddata);
+	else
+		barebox_non_pbl_start(membase, memsize, boarddata);
+}
diff --git a/arch/arm/cpu/entry.h b/arch/arm/cpu/entry.h
new file mode 100644
index 0000000..80fee57
--- /dev/null
+++ b/arch/arm/cpu/entry.h
@@ -0,0 +1,48 @@
+#ifndef __ENTRY_H__
+#define __ENTRY_H__
+
+#include <common.h>
+
+#if !defined (__PBL__)
+void __noreturn barebox_non_pbl_start(unsigned long membase,
+				      unsigned long memsize,
+				      void *boarddata);
+#else
+static inline
+void __noreturn barebox_non_pbl_start(unsigned long membase,
+				      unsigned long memsize,
+				      void *boarddata)
+{
+	hang();
+};
+#endif
+
+#if defined (__PBL__) && defined(CONFIG_PBL_MULTI_IMAGES)
+void __noreturn barebox_multi_pbl_start(unsigned long membase,
+					unsigned long memsize,
+					void *boarddata);
+#else
+static inline
+void __noreturn barebox_multi_pbl_start(unsigned long membase,
+					unsigned long memsize,
+					void *boarddata)
+{
+	hang();
+}
+#endif
+
+#if defined (__PBL__) && defined(CONFIG_PBL_SINGLE_IMAGE)
+void __noreturn barebox_single_pbl_start(unsigned long membase,
+					 unsigned long memsize,
+					 void *boarddata);
+#else
+static inline
+void __noreturn barebox_single_pbl_start(unsigned long membase,
+					 unsigned long memsize,
+					 void *boarddata)
+{
+	hang();
+}
+#endif
+
+#endif
diff --git a/arch/arm/cpu/start-pbl.c b/arch/arm/cpu/start-pbl.c
index f2490fd..2075ffe 100644
--- a/arch/arm/cpu/start-pbl.c
+++ b/arch/arm/cpu/start-pbl.c
@@ -45,7 +45,7 @@ void __naked __section(.text_head_entry) pbl_start(void)
 extern void *input_data;
 extern void *input_data_end;

-static noinline __noreturn void __barebox_arm_entry(unsigned long membase,
+__noreturn void barebox_single_pbl_start(unsigned long membase,
 		unsigned long memsize, void *boarddata)
 {
 	uint32_t offset;
@@ -56,8 +56,6 @@ static noinline __noreturn void __barebox_arm_entry(unsigned long membase,

 	endmem -= STACK_SIZE; /* stack */

-	arm_early_mmu_cache_invalidate();
-
 	if (IS_ENABLED(CONFIG_PBL_RELOCATABLE))
 		relocate_to_current_adr();

@@ -106,28 +104,3 @@ static noinline __noreturn void __barebox_arm_entry(unsigned long membase,

 	barebox(membase, memsize, boarddata);
 }
-
-/*
- * Main ARM entry point in the compressed image. Call this with the memory
- * region you can spare for barebox. This doesn't necessarily have to be the
- * full SDRAM. The currently running binary can be inside or outside of this
- * region. TEXT_BASE can be inside or outside of this region. boarddata will
- * be preserved and can be accessed later with barebox_arm_boarddata().
- *
- * -> membase + memsize
- *   STACK_SIZE              - stack
- *   16KiB, aligned to 16KiB - First level page table if early MMU support
- *                             is enabled
- *   128KiB                  - early memory space
- * -> maximum end of barebox binary
- *
- * Usually a TEXT_BASE of 1MiB below your lowest possible end of memory should
- * be fine.
- */
-void __naked __noreturn barebox_arm_entry(unsigned long membase,
-		unsigned long memsize, void *boarddata)
-{
-	arm_setup_stack(membase + memsize - 16);
-
-	__barebox_arm_entry(membase, memsize, boarddata);
-}
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 066dad8..82ec1ac 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -63,7 +63,7 @@ static uint32_t get_any_boarddata_magic(const void *boarddata)
 	return 0;
 }

-static noinline __noreturn void __start(unsigned long membase,
+__noreturn void barebox_non_pbl_start(unsigned long membase,
 		unsigned long memsize, void *boarddata)
 {
 	unsigned long endmem = membase + memsize;
@@ -165,31 +165,6 @@ void __naked __section(.text_entry) start(void)
 	barebox_arm_head();
 }

-/*
- * Main ARM entry point in the uncompressed image. Call this with the memory
- * region you can spare for barebox. This doesn't necessarily have to be the
- * full SDRAM. The currently running binary can be inside or outside of this
- * region. TEXT_BASE can be inside or outside of this region. boarddata will
- * be preserved and can be accessed later with barebox_arm_boarddata().
- *
- * -> membase + memsize
- *   STACK_SIZE              - stack
- *   16KiB, aligned to 16KiB - First level page table if early MMU support
- *                             is enabled
- * -> maximum end of barebox binary
- *
- * Usually a TEXT_BASE of 1MiB below your lowest possible end of memory should
- * be fine.
- */
-void __naked __noreturn barebox_arm_entry(unsigned long membase,
-		unsigned long memsize, void *boarddata)
-{
-	arm_setup_stack(membase + memsize - 16);
-
-	arm_early_mmu_cache_invalidate();
-
-	__start(membase, memsize, boarddata);
-}
 #else
 /*
  * First function in the uncompressed image. We get here from
@@ -198,6 +173,6 @@ void __naked __noreturn barebox_arm_entry(unsigned long membase,
 void __naked __section(.text_entry) start(unsigned long membase,
 		unsigned long memsize, void *boarddata)
 {
-	__start(membase, memsize, boarddata);
+	barebox_non_pbl_start(membase, memsize, boarddata);
 }
 #endif
diff --git a/arch/arm/cpu/uncompress.c b/arch/arm/cpu/uncompress.c
index b0b7c6d..dbf6b1e 100644
--- a/arch/arm/cpu/uncompress.c
+++ b/arch/arm/cpu/uncompress.c
@@ -41,7 +41,7 @@ static int __attribute__((__used__))
 	__attribute__((__section__(".image_end")))
 	__image_end_dummy = 0xdeadbeef;

-static void __noreturn noinline uncompress_start_payload(unsigned long membase,
+void __noreturn barebox_multi_pbl_start(unsigned long membase,
 		unsigned long memsize, void *boarddata)
 {
 	uint32_t pg_len;
@@ -52,8 +52,6 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase,
 	void *pg_start;
 	unsigned long pc = get_pc();

-	arm_early_mmu_cache_invalidate();
-
 	endmem -= STACK_SIZE; /* stack */

 	image_end = (void *)ld_var(__image_end) - get_runtime_offset();
@@ -114,15 +112,3 @@ static void __noreturn noinline uncompress_start_payload(unsigned long membase,

 	barebox(membase, memsize, boarddata);
 }
-
-/*
- * For the multi images startup process board code jumps here. We will uncompress
- * the attached barebox image and start it.
- */
-void __naked __noreturn barebox_arm_entry(unsigned long membase,
-		unsigned long memsize, void *boarddata)
-{
-	arm_setup_stack(membase + memsize - 16);
-
-	uncompress_start_payload(membase, memsize, boarddata);
-}
--
2.1.4

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] ARM: Add support for semihosting
  2015-10-28 18:34 [PATCH v2] ARM: Add support for semihosting Andrey Smirnov
  2015-10-28 18:34 ` [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start() Andrey Smirnov
  2015-10-28 18:34 ` [PATCH v2 2/2] arm/cpu: Avoid multiple definitions of barebox_arm_entry Andrey Smirnov
@ 2015-10-30  7:10 ` Sascha Hauer
  2 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2015-10-30  7:10 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

On Wed, Oct 28, 2015 at 11:34:36AM -0700, Andrey Smirnov wrote:
> Add semihosting API implementation and implement a filesystem driver
> to access debugging host filesystem using it.
> 
> Tested on Freescale SabreSD board (i.MX6Q) using OpenOCD
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---

Applied this one, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start().
  2015-10-28 18:34 ` [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start() Andrey Smirnov
@ 2015-10-30  7:20   ` Sascha Hauer
  2015-10-30 16:16     ` Andrey Smirnov
  0 siblings, 1 reply; 6+ messages in thread
From: Sascha Hauer @ 2015-10-30  7:20 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox

On Wed, Oct 28, 2015 at 11:34:37AM -0700, Andrey Smirnov wrote:
> Both barebox_boarddata and barebox_boot_dtb perform essentially the
> same function -- hold a pointer to a chunk of private data. Since only
> one variable is ever used at any given time we may as well merge those
> two variable into one. This also allows us to share more code between
> two boot paths (board data vs. device tree)
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
> 
> Changes since v1:
> 	- Unified barebox_boarddata and barebox_boot_dtb into
>           barebox_private_data which allowed to simplify distilled code
>           and avoid using double star pointers
> 
> 
>  arch/arm/cpu/start.c | 58 +++++++++++++++++++++++++++++++++-------------------
>  1 file changed, 37 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
> index 8e5097b..066dad8 100644
> --- a/arch/arm/cpu/start.c
> +++ b/arch/arm/cpu/start.c
> @@ -32,25 +32,35 @@
>  #include "mmu-early.h"
> 
>  unsigned long arm_stack_top;
> -static void *barebox_boarddata;
> +static void *barebox_private_data;
> 
>  u32 barebox_arm_machine(void)
>  {
>  	struct barebox_arm_boarddata *bd;
> 
> -	if (!barebox_boarddata)
> +	if (!barebox_private_data)
>  		return 0;
> 
> -	bd = barebox_boarddata;
> +	bd = barebox_private_data;
> 
>  	return bd->machine;
>  }
> 
> -static void *barebox_boot_dtb;
> -
>  void *barebox_arm_boot_dtb(void)
>  {
> -	return barebox_boot_dtb;
> +	return barebox_private_data;
> +}

Previously we knew that the pointer barebox_arm_machine() works on is a
machine type entry and we knew that the pointer returned from
barebox_arm_boot_dtb() is a dtb. With this patch both are share the same
pointer so we would have to check if the result returned from
barebox_arm_boot_dtb() is actually a dtb. That's not so nice.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start().
  2015-10-30  7:20   ` Sascha Hauer
@ 2015-10-30 16:16     ` Andrey Smirnov
  0 siblings, 0 replies; 6+ messages in thread
From: Andrey Smirnov @ 2015-10-30 16:16 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

>
> Previously we knew that the pointer barebox_arm_machine() works on is a
> machine type entry and we knew that the pointer returned from
> barebox_arm_boot_dtb() is a dtb. With this patch both are share the same
> pointer so we would have to check if the result returned from
> barebox_arm_boot_dtb() is actually a dtb. That's not so nice.

That is only partially true. The code before this patch assigned the
value of `boarddata` to `barebox_boarddata` unconditionally before it
did any checks of the contents validity, so there were no real
guarantees about barebox_arm_machine().

And we can add those checks to the code of barebox_arm_machine() and
barebox_arm_boot_dtb() and restore the original semantics.

>
> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-10-30 16:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-28 18:34 [PATCH v2] ARM: Add support for semihosting Andrey Smirnov
2015-10-28 18:34 ` [PATCH v2 1/2] arm/cpu/start.c: Distil some common code in __start() Andrey Smirnov
2015-10-30  7:20   ` Sascha Hauer
2015-10-30 16:16     ` Andrey Smirnov
2015-10-28 18:34 ` [PATCH v2 2/2] arm/cpu: Avoid multiple definitions of barebox_arm_entry Andrey Smirnov
2015-10-30  7:10 ` [PATCH v2] ARM: Add support for semihosting Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox