lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1337693217-15466-6-git-send-email-sjur.brandeland@stericsson.com>
Date:	Tue, 22 May 2012 15:26:56 +0200
From:	sjur.brandeland@...ricsson.com
To:	Ohad Ben-Cohen <ohad@...ery.com>
Cc:	Loic PALLARDY <loic.pallardy@...ricsson.com>,
	Ludovic BARRE <ludovic.barre@...ricsson.com>,
	linux-kernel@...r.kernel.org, Arnd Bergmann <arnd@...db.de>,
	Linus Walleij <linus.walleij@...aro.org>,
	Sjur Brændeland <sjurbren@...il.com>,
	Sjur Brændeland <sjur.brandeland@...ricsson.com>
Subject: [RFC 5/6] remoteproc: Support custom firmware handlers

From: Sjur Brændeland <sjur.brandeland@...ricsson.com>

Make the firmware handling customizable by creating
a rproc_fw_ops structure. Expose the existing
Elf firmware handling in rproc_elf_fw_ops.

Signed-off-by: Sjur Brændeland <sjur.brandeland@...ricsson.com>
---
 drivers/remoteproc/omap_remoteproc.c       |    1 +
 drivers/remoteproc/remoteproc_core.c       |   26 +++++++++++++++++---------
 drivers/remoteproc/remoteproc_elf_loader.c |   11 +++++++++--
 include/linux/remoteproc.h                 |   23 ++++++++++++++++++-----
 4 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index 69425c4..53ceaab 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -171,6 +171,7 @@ static struct rproc_ops omap_rproc_ops = {
 	.start		= omap_rproc_start,
 	.stop		= omap_rproc_stop,
 	.kick		= omap_rproc_kick,
+	.fw		= &rproc_elf_fw_ops
 };
 
 static int __devinit omap_rproc_probe(struct platform_device *pdev)
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 33384e6..75984ad 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -36,7 +36,6 @@
 #include <linux/remoteproc.h>
 #include <linux/iommu.h>
 #include <linux/klist.h>
-#include <linux/elf.h>
 #include <linux/virtio_ids.h>
 #include <linux/virtio_ring.h>
 #include <asm/byteorder.h>
@@ -781,12 +780,13 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
 {
 	struct device *dev = rproc->dev;
 	const char *name = rproc->firmware;
-	struct elf32_hdr *ehdr;
 	struct resource_table *table;
 	int ret, tablesz;
 
-	ehdr = (struct elf32_hdr *)fw->data;
-
+	if (!rproc->ops->fw_ops || !try_module_get(rproc->ops->fw_ops->owner)) {
+		dev_err(dev, "%s: can't get fw_ops->owner\n", __func__);
+		ret = -EINVAL;
+	}
 	dev_info(dev, "Booting fw image %s, size %zd\n", name, fw->size);
 
 	/*
@@ -796,11 +796,11 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
 	ret = rproc_enable_iommu(rproc);
 	if (ret) {
 		dev_err(dev, "can't enable iommu: %d\n", ret);
-		return ret;
+		goto out;
 	}
 
 	/* look for the resource table */
-	table = rproc_find_rsc_table(rproc, fw, &tablesz);
+	table = rproc->ops->fw_ops->find_rsc_table(rproc, fw, &tablesz);
 	if (!table) {
 		ret = -EINVAL;
 		goto clean_up;
@@ -813,8 +813,8 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
 		goto clean_up;
 	}
 
-	/* load the ELF segments to memory */
-	ret = rproc_load_segments(rproc, fw);
+	/* load the firmware to memory */
+	ret = rproc->ops->fw_ops->load_fw(rproc, fw);
 	if (ret) {
 		dev_err(dev, "Failed to load program segments: %d\n", ret);
 		goto clean_up;
@@ -836,6 +836,8 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
 clean_up:
 	rproc_resource_cleanup(rproc);
 	rproc_disable_iommu(rproc);
+out:
+	module_put(rproc->ops->fw_ops->owner);
 	return ret;
 }
 
@@ -853,8 +855,13 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
 	struct resource_table *table;
 	int ret, tablesz;
 
+	if (!rproc->ops->fw_ops || !try_module_get(rproc->ops->fw_ops->owner)) {
+		dev_err(rproc->dev, "%s: can't get fw_ops->owner\n", __func__);
+		return;
+	}
+
 	/* look for the resource table */
-	table = rproc_find_rsc_table(rproc, fw,  &tablesz);
+	table = rproc->ops->fw_ops->find_rsc_table(rproc, fw,  &tablesz);
 	if (!table)
 		goto out;
 
@@ -864,6 +871,7 @@ static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
 		goto out;
 
 out:
+	module_put(rproc->ops->fw_ops->owner);
 	if (fw)
 		release_firmware(fw);
 	/* allow rproc_unregister() contexts, if any, to proceed */
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index 3a1ae83..b90aeff 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -117,7 +117,7 @@ rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
  * directly allocate memory for every segment/resource. This is not yet
  * supported, though.
  */
-int
+static int
 rproc_load_segments(struct rproc *rproc, const struct firmware *fw)
 {
 	struct device *dev = rproc->dev;
@@ -198,7 +198,7 @@ rproc_load_segments(struct rproc *rproc, const struct firmware *fw)
  * size into @tablesz. If a valid table isn't found, NULL is returned
  * (and @tablesz isn't set).
  */
-struct resource_table *
+static struct resource_table *
 rproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
 							int *tablesz)
 {
@@ -271,3 +271,10 @@ rproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
 
 	return table;
 }
+
+struct rproc_fw_ops rproc_elf_fw_ops = {
+	.load_fw = rproc_load_segments,
+	.find_rsc_table = rproc_find_rsc_table,
+	.owner = THIS_MODULE
+};
+EXPORT_SYMBOL(rproc_elf_fw_ops);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 372d1a8..7ebb1ef 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -327,22 +327,33 @@ struct rproc_mem_entry {
 
 struct rproc;
 
-int
-rproc_load_segments(struct rproc *rproc, const struct firmware *fw);
-struct resource_table *
-rproc_find_rsc_table(struct rproc *rproc, const struct firmware *fw,
-								int *tablesz);
+/**
+ * struct rproc_fw_ops - firmware format specific operations.
+ * @find_rsc_table:	finds the resource table inside the firmware image.
+ * @load_fw:		load firmeware to memory, where the remote processor
+ *			expects to find it.
+ * @owner:		module owning the operations.
+ */
+struct rproc_fw_ops {
+	struct resource_table *(*find_rsc_table) (struct rproc *rproc,
+						const struct firmware *fw,
+						int *tablesz);
+	int (*load_fw)(struct rproc *rproc, const struct firmware *fw);
+	struct module *owner;
+};
 
 /**
  * struct rproc_ops - platform-specific device handlers
  * @start:	power on the device and boot it
  * @stop:	power off the device
  * @kick:	kick a virtqueue (virtqueue id given as a parameter)
+ * @fw_ops:	firmware operations for the remote processor
  */
 struct rproc_ops {
 	int (*start)(struct rproc *rproc);
 	int (*stop)(struct rproc *rproc);
 	void (*kick)(struct rproc *rproc, int vqid);
+	struct rproc_fw_ops *fw_ops;
 };
 
 /**
@@ -483,4 +494,6 @@ static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev)
 	return rvdev->rproc;
 }
 
+extern struct rproc_fw_ops rproc_elf_fw_ops;
+
 #endif /* REMOTEPROC_H */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ