diff --git a/tools/sloffs.c b/tools/sloffs.c
new file mode 100644
index 0000000..9abe9e7
--- /dev/null
+++ b/tools/sloffs.c
@@ -0,0 +1,180 @@
+/******************************************************************************
+ * Copyright (c) 2008 Adrian Reber
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ *     Adrian Reber - initial implementation
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <byteswap.h>
+#include <getopt.h>
+
+#include <calculatecrc.h>
+
+#define VERSION 1
+
+#ifdef _BIG_ENDIAN
+#define cpu_to_be64(x)  (x)
+#define be64_to_cpu(x)  (x)
+#else
+#define cpu_to_be64(x)  bswap_64(x)
+#define be64_to_cpu(x)  bswap_64(x)
+#endif
+
+
+/* no board dependencies wanted here, let's hardcode SLOF's
+ * magic strings here */
+
+#define FLASHFS_MAGIC "magic123"
+#define FLASHFS_PLATFORM_MAGIC "JS2XBlade"
+#define FLASHFS_PLATFORM_REVISION "1"
+
+/* there seems to be no structure defined anywhere in the code
+ * which resembles the actual sloffs/romfs file header;
+ * so defining it here for now */
+
+struct sloffs {
+	uint64_t next;
+	uint64_t len;
+	uint64_t flags;
+	uint64_t data;
+	char *name;
+};
+
+static struct sloffs *
+next_file(struct sloffs *sloffs)
+{
+	return (struct sloffs *)((unsigned char *)sloffs +
+				 be64_to_cpu(sloffs->next));
+}
+
+static void
+sloffs_list(const void *data)
+{
+	struct sloffs *sloffs = (struct sloffs *)data;
+	const char *name_header = "File Name";
+	int i;
+	int max;
+	int line;
+
+	/* find largest name */
+	max = strlen(name_header);;
+	for (;;) {
+		if (max < strlen((char *)&sloffs->name))
+			max = strlen((char *)&sloffs->name);
+
+		if (be64_to_cpu(sloffs->next) == 0)
+			break;
+		sloffs = next_file(sloffs);
+	}
+
+	/* have at least two spaces between name and size column */
+	max += 2;
+
+	/* header for listing */
+	line = printf("   Offset      ");
+	line += printf("%s", name_header);
+	for (i = 0; i < max - strlen(name_header); i++)
+		line += printf(" ");
+	line += printf("Size                ");
+	line += printf("Flags\n");
+	printf("   ");
+	for (i = 0; i <= line; i++)
+		printf("=");
+	printf("\n");
+
+	sloffs = (struct sloffs *)data;
+	for (;;) {
+		printf("   0x%08x", (void *)sloffs - (void *)data);
+		printf("  %s", (char *)&sloffs->name);
+		for (i = 0; i < max - strlen((char *)&sloffs->name); i++)
+			printf(" ");
+
+		printf("%07lld ", be64_to_cpu(sloffs->len));
+		printf("(0x%06llx)", be64_to_cpu(sloffs->len));
+		printf("  0x%08llx\n", be64_to_cpu(sloffs->flags));
+
+		if (be64_to_cpu(sloffs->next) == 0)
+			break;
+		sloffs = next_file(sloffs);
+	}
+}
+
+static void
+usage(void)
+{
+	printf("sloffs lists or changes a SLOF flash image\n\n");
+	printf("Usage:\n");
+	printf("  sloffs [OPTION]... [FILE]\n\n");
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int fd;
+	void *file;
+	struct stat stat;
+	const struct option loption[] = {
+		{ "help", 0, NULL, 'h' },
+		{ "list", 0, NULL, 'l' },
+		{ "version", 0, NULL, 'v' },
+		{ 0, 0, 0, 0 }
+	};
+	const char *soption = "hlv";
+	int c;
+	char mode;
+
+	for (;;) {
+		c = getopt_long(argc, argv, soption, loption, NULL);
+		if (c == -1)
+			break;
+		switch (c) {
+		case 'l':
+			mode = 'l';
+			break;
+		case 'v':
+			printf("sloffs (version %d)\n", VERSION);
+			exit(0);
+		case 'h':
+		default:
+			usage();
+		}
+	}
+
+	if (optind >= argc)
+		usage();
+
+	fd = open(argv[optind], O_RDONLY);
+
+	if (fd == -1) {
+		perror(argv[optind]);
+		exit(1);
+	}
+
+	fstat(fd, &stat);
+	file = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
+
+	switch (mode) {
+	case 'l':
+		sloffs_list(file);
+		break;
+	}
+
+	munmap(file, stat.st_size);
+	close(fd);
+	return 0;
+}
