[PATCH v2 4/4] remoteproc: qcom: Introduce WCNSS peripheral image loader

2015-12-27 Thread Bjorn Andersson
This introduces the peripheral image loader, for loading WCNSS firmware
and boot the core on e.g. MSM8974. The firmware is verified and booted
with the help of the Peripheral Authentication System (PAS) in
TrustZone.

Signed-off-by: Bjorn Andersson 
---

Changes since v1:
- Hard coding SMEM id for crash-reason and firmware name

All dependencies has been merges since v1.

 drivers/remoteproc/Kconfig   |  11 +
 drivers/remoteproc/Makefile  |   2 +
 drivers/remoteproc/qcom_mdt_loader.c | 213 ++
 drivers/remoteproc/qcom_mdt_loader.h |   8 +
 drivers/remoteproc/qcom_wcnss.c  | 550 +++
 5 files changed, 784 insertions(+)
 create mode 100644 drivers/remoteproc/qcom_mdt_loader.c
 create mode 100644 drivers/remoteproc/qcom_mdt_loader.h
 create mode 100644 drivers/remoteproc/qcom_wcnss.c

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 28c711f0ac6b..f4eb07907851 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -77,4 +77,15 @@ config DA8XX_REMOTEPROC
  It's safe to say n here if you're not interested in multimedia
  offloading.
 
+config QCOM_MDT_LOADER
+   tristate
+
+config QCOM_WCNSS_PIL
+   tristate "Qualcomm WCNSS Peripheral Image Loader"
+   depends on OF && ARCH_QCOM
+   select REMOTEPROC
+   select QCOM_MDT_LOADER
+   help
+ Peripherial Image Loader for the WCNSS block.
+
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 81b04d1e2e58..beb9a4be7ffd 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -11,3 +11,5 @@ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o
 obj-$(CONFIG_STE_MODEM_RPROC)  += ste_modem_rproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
+obj-$(CONFIG_QCOM_MDT_LOADER)  += qcom_mdt_loader.o
+obj-$(CONFIG_QCOM_WCNSS_PIL)   += qcom_wcnss.o
diff --git a/drivers/remoteproc/qcom_mdt_loader.c 
b/drivers/remoteproc/qcom_mdt_loader.c
new file mode 100644
index ..30d67f3e63c1
--- /dev/null
+++ b/drivers/remoteproc/qcom_mdt_loader.c
@@ -0,0 +1,213 @@
+/*
+ * Qualcomm Peripheral Image Loader
+ *
+ * Copyright (C) 2015 Sony Mobile Communications Inc
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "remoteproc_internal.h"
+
+#define segment_is_hash(flag) (((flag) & (0x7 << 24)) == (0x2 << 24))
+
+static int segment_is_loadable(const struct elf32_phdr *p)
+{
+   return (p->p_type == PT_LOAD) &&
+  !segment_is_hash(p->p_flags) &&
+  p->p_memsz;
+}
+
+/**
+ * rproc_mdt_sanity_check() - sanity check mdt firmware header
+ * @rproc: the remote processor handle
+ * @fw: the mdt header firmware image
+ *
+ * Returns 0 for a valid header, -EINVAL otherwise.
+ */
+int qcom_mdt_sanity_check(struct rproc *rproc,
+ const struct firmware *fw)
+{
+   struct elf32_hdr *ehdr;
+
+   if (!fw) {
+   dev_err(>dev, "failed to load %s\n", rproc->name);
+   return -EINVAL;
+   }
+
+   if (fw->size < sizeof(struct elf32_hdr)) {
+   dev_err(>dev, "image is too small\n");
+   return -EINVAL;
+   }
+
+   ehdr = (struct elf32_hdr *)fw->data;
+   if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+   dev_err(>dev, "image is corrupted (bad magic)\n");
+   return -EINVAL;
+   }
+
+   if (ehdr->e_phnum == 0) {
+   dev_err(>dev, "no loadable segments\n");
+   return -EINVAL;
+   }
+
+   if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
+   sizeof(struct elf32_hdr) > fw->size) {
+   dev_err(>dev, "firmware size is too small\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_mdt_sanity_check);
+
+/**
+ * qcom_mdt_find_rsc_table() - provide dummy resource table for remoteproc
+ * @rproc: remoteproc handle
+ * @fw:firmware header
+ * @tablesz:   outgoing size of the table
+ *
+ * Returns a dummy table.
+ */
+struct resource_table *qcom_mdt_find_rsc_table(struct rproc *rproc,
+  const struct firmware *fw,
+

[PATCH v2 4/4] remoteproc: qcom: Introduce WCNSS peripheral image loader

2015-12-27 Thread Bjorn Andersson
This introduces the peripheral image loader, for loading WCNSS firmware
and boot the core on e.g. MSM8974. The firmware is verified and booted
with the help of the Peripheral Authentication System (PAS) in
TrustZone.

Signed-off-by: Bjorn Andersson 
---

Changes since v1:
- Hard coding SMEM id for crash-reason and firmware name

All dependencies has been merges since v1.

 drivers/remoteproc/Kconfig   |  11 +
 drivers/remoteproc/Makefile  |   2 +
 drivers/remoteproc/qcom_mdt_loader.c | 213 ++
 drivers/remoteproc/qcom_mdt_loader.h |   8 +
 drivers/remoteproc/qcom_wcnss.c  | 550 +++
 5 files changed, 784 insertions(+)
 create mode 100644 drivers/remoteproc/qcom_mdt_loader.c
 create mode 100644 drivers/remoteproc/qcom_mdt_loader.h
 create mode 100644 drivers/remoteproc/qcom_wcnss.c

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 28c711f0ac6b..f4eb07907851 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -77,4 +77,15 @@ config DA8XX_REMOTEPROC
  It's safe to say n here if you're not interested in multimedia
  offloading.
 
+config QCOM_MDT_LOADER
+   tristate
+
+config QCOM_WCNSS_PIL
+   tristate "Qualcomm WCNSS Peripheral Image Loader"
+   depends on OF && ARCH_QCOM
+   select REMOTEPROC
+   select QCOM_MDT_LOADER
+   help
+ Peripherial Image Loader for the WCNSS block.
+
 endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index 81b04d1e2e58..beb9a4be7ffd 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -11,3 +11,5 @@ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o
 obj-$(CONFIG_STE_MODEM_RPROC)  += ste_modem_rproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
+obj-$(CONFIG_QCOM_MDT_LOADER)  += qcom_mdt_loader.o
+obj-$(CONFIG_QCOM_WCNSS_PIL)   += qcom_wcnss.o
diff --git a/drivers/remoteproc/qcom_mdt_loader.c 
b/drivers/remoteproc/qcom_mdt_loader.c
new file mode 100644
index ..30d67f3e63c1
--- /dev/null
+++ b/drivers/remoteproc/qcom_mdt_loader.c
@@ -0,0 +1,213 @@
+/*
+ * Qualcomm Peripheral Image Loader
+ *
+ * Copyright (C) 2015 Sony Mobile Communications Inc
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "remoteproc_internal.h"
+
+#define segment_is_hash(flag) (((flag) & (0x7 << 24)) == (0x2 << 24))
+
+static int segment_is_loadable(const struct elf32_phdr *p)
+{
+   return (p->p_type == PT_LOAD) &&
+  !segment_is_hash(p->p_flags) &&
+  p->p_memsz;
+}
+
+/**
+ * rproc_mdt_sanity_check() - sanity check mdt firmware header
+ * @rproc: the remote processor handle
+ * @fw: the mdt header firmware image
+ *
+ * Returns 0 for a valid header, -EINVAL otherwise.
+ */
+int qcom_mdt_sanity_check(struct rproc *rproc,
+ const struct firmware *fw)
+{
+   struct elf32_hdr *ehdr;
+
+   if (!fw) {
+   dev_err(>dev, "failed to load %s\n", rproc->name);
+   return -EINVAL;
+   }
+
+   if (fw->size < sizeof(struct elf32_hdr)) {
+   dev_err(>dev, "image is too small\n");
+   return -EINVAL;
+   }
+
+   ehdr = (struct elf32_hdr *)fw->data;
+   if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+   dev_err(>dev, "image is corrupted (bad magic)\n");
+   return -EINVAL;
+   }
+
+   if (ehdr->e_phnum == 0) {
+   dev_err(>dev, "no loadable segments\n");
+   return -EINVAL;
+   }
+
+   if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
+   sizeof(struct elf32_hdr) > fw->size) {
+   dev_err(>dev, "firmware size is too small\n");
+   return -EINVAL;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(qcom_mdt_sanity_check);
+
+/**
+ * qcom_mdt_find_rsc_table() - provide dummy resource table for remoteproc
+ * @rproc: remoteproc handle
+ * @fw:firmware header
+ * @tablesz:   outgoing size of the table
+ *
+ * Returns a dummy table.
+ */
+struct resource_table *qcom_mdt_find_rsc_table(struct rproc *rproc,
+  const struct firmware *fw,