db845c: qcom: Add userspace tools to talk to dsp and modem

Add Qcom userspace tools and their respective sepolicy rules.

Userspace tools are downloaded from following github:

To trigger loading of wlan firmware on SDM845
git clone https://github.com/andersson/pd-mapper

Userspace reference for net/qrtr in the Linux kernel
git clone https://github.com/andersson/qrtr

Qualcomm Remote Filesystem Service Implementation
git clone https://github.com/andersson/rmtfs

Trivial File Transfer Protocol server over AF_QIPCRTR
git clone https://github.com/andersson/tqftpserv

Change-Id: Ic466af6fef010a9b71c90e38205f49a876b001e2
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
diff --git a/qcom/rmtfs/storage.c b/qcom/rmtfs/storage.c
new file mode 100644
index 0000000..d31f757
--- /dev/null
+++ b/qcom/rmtfs/storage.c
@@ -0,0 +1,291 @@
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "rmtfs.h"
+
+#define MAX_CALLERS 10
+#define STORAGE_MAX_SIZE (16 * 1024 * 1024)
+
+#ifndef ANDROID
+#define BY_PARTLABEL_PATH "/dev/disk/by-partlabel"
+#else
+#define BY_PARTLABEL_PATH "/dev/block/by-name"
+#endif
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
+struct partition {
+	const char *path;
+	const char *actual;
+	const char *partlabel;
+};
+
+struct rmtfd {
+	unsigned id;
+	unsigned node;
+	int fd;
+	unsigned dev_error;
+	const struct partition *partition;
+
+	void *shadow_buf;
+	size_t shadow_len;
+};
+
+static const char *storage_dir = "/boot";
+static int storage_read_only;
+static int storage_use_partitions;
+
+static const struct partition partition_table[] = {
+	{ "/boot/modem_fs1", "modem_fs1", "modemst1" },
+	{ "/boot/modem_fs2", "modem_fs2", "modemst2" },
+	{ "/boot/modem_fsc", "modem_fsc", "fsc" },
+	{ "/boot/modem_fsg", "modem_fsg", "fsg" },
+	{}
+};
+
+static struct rmtfd rmtfds[MAX_CALLERS];
+
+static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file);
+
+int storage_init(const char *storage_root, bool read_only, bool use_partitions)
+{
+	int i;
+
+	if (storage_root)
+		storage_dir = storage_root;
+
+	if (use_partitions) {
+		storage_dir = BY_PARTLABEL_PATH;
+		storage_use_partitions = true;
+	}
+
+	storage_read_only = read_only;
+
+	for (i = 0; i < MAX_CALLERS; i++) {
+		rmtfds[i].id = i;
+		rmtfds[i].fd = -1;
+		rmtfds[i].shadow_buf = NULL;
+	}
+
+	return 0;
+}
+
+struct rmtfd *storage_open(unsigned node, const char *path)
+{
+	char *fspath;
+	const struct partition *part;
+	struct rmtfd *rmtfd = NULL;
+	const char *file;
+	size_t pathlen;
+	int saved_errno;
+	int ret;
+	int fd;
+	int i;
+
+	for (part = partition_table; part->path; part++) {
+		if (strcmp(part->path, path) == 0)
+			goto found;
+	}
+
+	fprintf(stderr, "[RMTFS storage] request for unknown partition '%s', rejecting\n", path);
+	return NULL;
+
+found:
+	/* Check if this node already has the requested path open */
+	for (i = 0; i < MAX_CALLERS; i++) {
+		if ((rmtfds[i].fd != -1 || rmtfds[i].shadow_buf) &&
+		    rmtfds[i].node == node &&
+		    rmtfds[i].partition == part)
+			return &rmtfds[i];
+	}
+
+	for (i = 0; i < MAX_CALLERS; i++) {
+		if (rmtfds[i].fd == -1 && !rmtfds[i].shadow_buf) {
+			rmtfd = &rmtfds[i];
+			break;
+		}
+	}
+	if (!rmtfd) {
+		fprintf(stderr, "[storage] out of free rmtfd handles\n");
+		return NULL;
+	}
+
+	if (storage_use_partitions)
+		file = part->partlabel;
+	else
+		file = part->actual;
+
+	pathlen = strlen(storage_dir) + strlen(file) + 2;
+	fspath = alloca(pathlen);
+	snprintf(fspath, pathlen, "%s/%s", storage_dir, file);
+	if (!storage_read_only) {
+		fd = open(fspath, O_RDWR);
+		if (fd < 0) {
+			saved_errno = errno;
+			fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
+					fspath, part->path, strerror(saved_errno));
+			errno = saved_errno;
+			return NULL;
+		}
+		rmtfd->fd = fd;
+		rmtfd->shadow_len = 0;
+	} else {
+		ret = storage_populate_shadow_buf(rmtfd, fspath);
+		if (ret < 0) {
+			saved_errno = errno;
+			fprintf(stderr, "[storage] failed to open '%s' (requested '%s'): %s\n",
+					fspath, part->path, strerror(saved_errno));
+			errno = saved_errno;
+			return NULL;
+		}
+	}
+
+	rmtfd->node = node;
+	rmtfd->partition = part;
+
+	return rmtfd;
+}
+
+void storage_close(struct rmtfd *rmtfd)
+{
+	close(rmtfd->fd);
+	rmtfd->fd = -1;
+
+	free(rmtfd->shadow_buf);
+	rmtfd->shadow_buf = NULL;
+	rmtfd->shadow_len = 0;
+
+	rmtfd->partition = NULL;
+}
+
+struct rmtfd *storage_get(unsigned node, int caller_id)
+{
+	struct rmtfd *rmtfd;
+
+	if (caller_id >= MAX_CALLERS)
+		return NULL;
+
+	rmtfd = &rmtfds[caller_id];
+	if (rmtfd->node != node)
+		return NULL;
+
+	return rmtfd;
+}
+
+int storage_get_caller_id(const struct rmtfd *rmtfd)
+{
+	return rmtfd->id;
+}
+
+int storage_get_error(const struct rmtfd *rmtfd)
+{
+	return rmtfd->dev_error;
+}
+
+void storage_exit(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_CALLERS; i++) {
+		if (rmtfds[i].fd >= 0)
+			close(rmtfds[i].fd);
+	}
+}
+
+ssize_t storage_pread(const struct rmtfd *rmtfd, void *buf, size_t nbyte, off_t offset)
+{
+	ssize_t n;
+
+	if (!storage_read_only) {
+		n = pread(rmtfd->fd, buf, nbyte, offset);
+	} else {
+		n = MIN(nbyte, rmtfd->shadow_len - offset);
+		if (n > 0)
+			memcpy(buf, rmtfd->shadow_buf + offset, n);
+		else
+			n = 0;
+	}
+
+	if (n < nbyte)
+		memset(buf + n, 0, nbyte - n);
+
+	return nbyte;
+}
+
+ssize_t storage_pwrite(struct rmtfd *rmtfd, const void *buf, size_t nbyte, off_t offset)
+{
+	size_t new_len = offset + nbyte;
+	void *new_buf;
+
+	if (!storage_read_only)
+		return pwrite(rmtfd->fd, buf, nbyte, offset);
+
+	if (new_len >= STORAGE_MAX_SIZE) {
+		fprintf(stderr, "write to %zd bytes exceededs max size\n", new_len);
+		errno = -EINVAL;
+		return -1;
+	}
+
+	if (new_len > rmtfd->shadow_len) {
+		new_buf = realloc(rmtfd->shadow_buf, new_len);
+		if (!new_buf) {
+			errno = -ENOMEM;
+			return -1;
+		}
+
+		rmtfd->shadow_buf = new_buf;
+		rmtfd->shadow_len = new_len;
+	}
+
+	memcpy(rmtfd->shadow_buf + offset, buf, nbyte);
+
+	return nbyte;
+}
+
+static int storage_populate_shadow_buf(struct rmtfd *rmtfd, const char *file)
+{
+	ssize_t len;
+	ssize_t n;
+	void *buf;
+	int ret;
+	int fd;
+
+	fd = open(file, O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	len = lseek(fd, 0, SEEK_END);
+	if (len < 0) {
+		ret = -1;
+		goto err_close_fd;
+	}
+
+	lseek(fd, 0, SEEK_SET);
+
+	buf = calloc(1, len);
+	if (!buf) {
+		ret = -1;
+		goto err_close_fd;
+	}
+
+	n = read(fd, buf, len);
+	if (n < 0) {
+		ret = -1;
+		goto err_close_fd;
+	}
+
+	rmtfd->shadow_buf = buf;
+	rmtfd->shadow_len = n;
+
+	ret = 0;
+
+err_close_fd:
+	close(fd);
+
+	return ret;
+}