From 45c70af462edd6fb2cb6962545971a8a3ec78806 Mon Sep 17 00:00:00 2001
From: Alessandro Rubini <rubini@gnudd.com>
Date: Mon, 15 Sep 2014 11:40:59 +0200
Subject: [PATCH 14/14] commands: add sdb commands to list, read, setvar

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
---
 commands/Kconfig  |    7 ++
 commands/Makefile |    1 +
 commands/sdb.c    |  220 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 228 insertions(+)
 create mode 100644 commands/sdb.c

diff --git a/commands/Kconfig b/commands/Kconfig
index 352e8bf..89cadec 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -756,6 +756,13 @@ config CMD_DETECT
 	  actual probe of the client devices until they are needed. Use the
 	  'detect' command on the physical device to trigger probing.
 
+config CMD_SDB
+	bool
+	select LIBSDB
+	prompt "commands for reading SDB information"
+	help
+	  This enables "sdbinfo", "sdbset" and "sdbread".
+
 menuconfig CMD_WD
 	bool
 	depends on WATCHDOG
diff --git a/commands/Makefile b/commands/Makefile
index 91ec0e9..e97291e 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_CMD_FILETYPE)	+= filetype.o
 obj-$(CONFIG_CMD_BAREBOX_UPDATE)+= barebox-update.o
 obj-$(CONFIG_CMD_MIITOOL)	+= miitool.o
 obj-$(CONFIG_CMD_DETECT)	+= detect.o
+obj-$(CONFIG_CMD_SDB)		+= sdb.o
 obj-$(CONFIG_CMD_BOOT)		+= boot.o
 obj-$(CONFIG_CMD_DEVINFO)	+= devinfo.o
 obj-$(CONFIG_CMD_READF)		+= readf.o
diff --git a/commands/sdb.c b/commands/sdb.c
new file mode 100644
index 0000000..6b8e358
--- /dev/null
+++ b/commands/sdb.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014 CERN.
+ * Author: Alessandro Rubini for BE-CO-HT (White Rabbit project)
+ *
+ * Please use according to GNU GPL 2 or later
+ */
+#include <common.h>
+#include <command.h>
+#include <init.h>
+#include <malloc.h>
+#include <errno.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <xfuncs.h>
+#include <environment.h>
+
+#include <../lib/sdb/libsdbfs.h> /* hackish */
+
+#define BUFSIZE 1024 /* like cat.c in this directory */
+
+/* This is the drvdata in the SDB information */
+struct bb_sdb_drvdata {
+	int fd;
+};
+
+static struct bb_sdb_drvdata drvdata;
+
+/* and how to read the thing: use straight barebox POSIX interface */
+static int bb_sdb_read(struct sdbfs *fs, int offset, void *buf, int count)
+{
+	struct bb_sdb_drvdata *dd = fs->drvdata;
+	int fd = dd->fd;
+
+	if (lseek(fd, offset, SEEK_SET) < 0)
+		return -1;
+	return read(fd, buf, count);
+}
+
+static struct sdbfs bb_sdb_instance = {
+	.drvdata = &drvdata,
+	.entrypoint = 0, /* unfortunately: to be fixed */
+	.read = bb_sdb_read,
+};
+
+/* local helpers to open and close, we do it three times on static data */
+static int bb_sdb_create(char *name)
+{
+	int fd, ret;
+	fd = open(name, O_RDONLY);
+
+	if (fd < 0) {
+		printf("could not open %s: %s\n", name, errno_str());
+		return fd;
+	}
+	drvdata.fd = fd;
+	ret = sdbfs_dev_create(&bb_sdb_instance, 1 /* verbose */);
+	if (ret != 0) {
+		printf("Error accessing SDB filesystem in \"%s\"\n",
+		       name);
+	}
+	return ret;
+}
+
+static int bb_sdb_destroy(void)
+{
+	return sdbfs_dev_destroy(&bb_sdb_instance);
+}
+
+/* And finally the real commands */
+static int do_sdbinfo(int argc, char *argv[])
+{
+	struct sdb_device *d;
+	struct sdb_product *p;
+	struct sdb_component *c;
+	int new;
+
+	if (argc != 2) {
+		perror("sdbinfo");
+		return 1;
+	}
+	if (bb_sdb_create(argv[1]) != 0)
+		return 1;
+	/* now we already identified the magic number and so on */
+
+	new = 1;
+	while ( (d = sdbfs_scan(&bb_sdb_instance, new)) != NULL) {
+		new = 0; /* for next time */
+
+		c = &d->sdb_component;
+		p = &c->product;
+
+		printf("%016llx:%08x @ %08llx-%08llx ",
+		       ntohll(p->vendor_id), ntohl(p->device_id),
+		       ntohll(c->addr_first), ntohll(c->addr_last));
+		printf("%.19s\n", p->name);
+        }
+	return bb_sdb_destroy();
+}
+
+static int do_sdbset(int argc, char *argv[])
+{
+	char *buf;
+	char *filename;
+	int i, j, err = 1;
+
+	if (argc < 3 || argc > 4) {
+		perror("sdbset");
+		return 1;
+	}
+	if (bb_sdb_create(argv[1]) != 0)
+		return 1;
+	/* now we already identified the magic number and so on */
+
+	filename = argv[argc - 1];
+	i = sdbfs_open_name(&bb_sdb_instance, filename);
+	if (i < 0) {
+		printf("can't open \"%s\" in \"%s\"\n", filename, argv[1]);
+		goto out;
+	}
+	buf = xmalloc(BUFSIZE);
+	i = sdbfs_fread(&bb_sdb_instance, -1, buf, BUFSIZE);
+	sdbfs_close(&bb_sdb_instance);
+
+	if (i > 0) {
+		j = i - 1;
+		/* trim trailing garbage as the file is assumed to be text */
+		while (j && (buf[j] == 0xff  || buf[j] == 0x00))
+			j--;
+	}
+	if (i > 0 && buf[i - 1] == '\n')
+		i--; /* remove trailing newline too */
+	if (i > 0) {
+		buf[i] = '\0';
+		setenv(argv[2], buf);
+	}
+	free(buf);
+	sdbfs_close(&bb_sdb_instance);
+	err = 0;
+out:
+	bb_sdb_destroy();
+	return err;
+}
+
+/*
+ * Read a file, skipping trailing 0x00 or 0xff bytes, as a convenience.
+ * The function is based on local command cat, in this director (Sascha Hauer)
+ */
+static int do_sdbread(int argc, char *argv[])
+{
+	char *buf;
+	int i, j, err = 1;
+
+	if (argc != 3) {
+		perror("sdbread");
+		return 1;
+	}
+
+	if (bb_sdb_create(argv[1]) != 0)
+		return 1;
+	/* now we already identified the magic number and so on */
+
+	i = sdbfs_open_name(&bb_sdb_instance, argv[2]);
+	if (i < 0) {
+		printf("can't open \"%s\" in \"%s\"\n", argv[2], argv[1]);
+		goto out;
+	}
+	buf = xmalloc(BUFSIZE);
+
+	while ( (i = sdbfs_fread(&bb_sdb_instance, -1, buf, BUFSIZE)) > 0) {
+
+		/* trim trailing garbage as the file is assumed to be text */
+		j = i - 1;
+		while (j > 0 && (buf[j] == 0xff  || buf[j] == 0x00))
+			j--;
+		for (i = 0; i <= j; i++)
+			putchar(buf[i]);
+		/* no ctrl-C support; this is expected to be fast */
+	}
+	/* most files have the trailing newline alrady, avoid adding it */
+	free(buf);
+	sdbfs_close(&bb_sdb_instance);
+	err = 0;
+out:
+	bb_sdb_destroy();
+	return err;
+}
+
+static const __maybe_unused char cmd_sdbinfo_help[] =
+"Usage: sdbinfo <dev>"
+"\n"
+"List SDB files inside <dev>. Currently entry point must be zero";
+
+BAREBOX_CMD_START(sdbinfo)
+	.cmd		= do_sdbinfo,
+	.usage		= "sdb information in device",
+	BAREBOX_CMD_HELP(cmd_sdbinfo_help)
+BAREBOX_CMD_END
+
+static const __maybe_unused char cmd_sdbset_help[] =
+"Usage: sdbset <dev> <varname> [<sdbfile>]"
+"\n"
+"Set a variable from the content of an SDB file in <dev>\n";
+
+BAREBOX_CMD_START(sdbset)
+	.cmd		= do_sdbset,
+	.usage		= "set a variable from an SDB file",
+	BAREBOX_CMD_HELP(cmd_sdbset_help)
+BAREBOX_CMD_END
+
+static const __maybe_unused char cmd_sdbread_help[] =
+"Usage: sdbread <dev> <file>"
+"\n"
+"Print contents of file to stdout\n";
+
+BAREBOX_CMD_START(sdbread)
+	.cmd		= do_sdbread,
+	.usage		= "cat an SDB file",
+	BAREBOX_CMD_HELP(cmd_sdbread_help)
+BAREBOX_CMD_END
+
-- 
1.7.10.4

