All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jordan Crouse <jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
To: freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [PATCH 15/16] drm/msm: Add a quick and dirty PIL loader
Date: Fri,  4 Nov 2016 16:44:56 -0600	[thread overview]
Message-ID: <1478299497-9729-16-git-send-email-jcrouse@codeaurora.org> (raw)
In-Reply-To: <1478299497-9729-1-git-send-email-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>

In order to switch the GPU out of secure mode on most systems we
need to load a zap shader into memory and get it authenticated
and into the secure world.  All the bits and pieces to do
the load are scattered throughout the kernel, but we need to
bring everything together.

Add a semi-custom loader that will read a MDT file and get
it loaded and authenticated through SCM.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 166 ++++++++++++++++++++++++++++++++++
 1 file changed, 166 insertions(+)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 997ae31..c4a9a12 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -11,12 +11,178 @@
  *
  */
 
+#include <linux/elf.h>
+#include <linux/types.h>
+#include <linux/cpumask.h>
+#include <linux/qcom_scm.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_reserved_mem.h>
 #include "msm_gem.h"
 #include "a5xx_gpu.h"
 
 extern bool hang_debug;
 static void a5xx_dump(struct msm_gpu *gpu);
 
+static inline bool _check_segment(const struct elf32_phdr *phdr)
+{
+	return ((phdr->p_type == PT_LOAD) &&
+		((phdr->p_flags & (7 << 24)) != (2 << 24)) &&
+		phdr->p_memsz);
+}
+
+static int __pil_tz_load_image(struct platform_device *pdev,
+		const struct firmware *mdt, const char *fwname,
+		void *fwptr, size_t fw_size, unsigned long fw_min_addr)
+{
+	char str[64] = { 0 };
+	const struct elf32_hdr *ehdr = (struct elf32_hdr *) mdt->data;
+	const struct elf32_phdr *phdrs = (struct elf32_phdr *) (ehdr + 1);
+	const struct firmware *fw;
+	int i, ret = 0;
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		const struct elf32_phdr *phdr = &phdrs[i];
+		size_t offset;
+
+		/* Make sure the segment is loadable */
+		if (!_check_segment(phdr))
+			continue;
+
+		/* Get the offset of the segment within the region */
+		offset = (phdr->p_paddr - fw_min_addr);
+
+		/* Request the file containing the segment */
+		snprintf(str, sizeof(str) - 1, "%s.b%02d", fwname, i);
+
+		ret = request_firmware(&fw, str, &pdev->dev);
+		if (ret) {
+			dev_err(&pdev->dev, "Failed to load segment %s\n", str);
+			break;
+		}
+
+		if (offset + fw->size > fw_size) {
+			dev_err(&pdev->dev, "Segment %s is too big\n", str);
+			ret = -EINVAL;
+			release_firmware(fw);
+			break;
+		}
+
+		/* Copy the segment into place */
+		memcpy(fwptr + offset, fw->data, fw->size);
+		release_firmware(fw);
+	}
+
+	return ret;
+}
+
+static int _pil_tz_load_image(struct platform_device *pdev)
+{
+	char str[64] = { 0 };
+	const char *fwname;
+	const struct elf32_hdr *ehdr;
+	const struct elf32_phdr *phdrs;
+	const struct firmware *mdt;
+	phys_addr_t fw_min_addr, fw_max_addr;
+	dma_addr_t fw_phys;
+	size_t fw_size;
+	u32 pas_id;
+	void *ptr;
+	int i, ret;
+
+	if (pdev == NULL)
+		return -ENODEV;
+
+	if (!qcom_scm_is_available()) {
+		dev_err(&pdev->dev, "SCM is not available\n");
+		return -EINVAL;
+	}
+
+	ret = of_reserved_mem_device_init(&pdev->dev);
+
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to set up the reserved memory\n");
+		return ret;
+	}
+
+	/* Get the firmware and PAS id from the device node */
+	if (of_property_read_string(pdev->dev.of_node, "qcom,firmware",
+		&fwname)) {
+		dev_err(&pdev->dev, "Could not read a firmware name\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(pdev->dev.of_node, "qcom,pas-id", &pas_id)) {
+		dev_err(&pdev->dev, "Could not read the pas ID\n");
+		return -EINVAL;
+	}
+
+	snprintf(str, sizeof(str) - 1, "%s.mdt", fwname);
+
+	/* Request the MDT file for the firmware */
+	ret = request_firmware(&mdt, str, &pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to load %s\n", str);
+		return ret;
+	}
+
+	ehdr = (struct elf32_hdr *) mdt->data;
+	phdrs = (struct elf32_phdr *) (ehdr + 1);
+
+	/* Get the extents of the firmware image */
+
+	fw_min_addr = (phys_addr_t) ULLONG_MAX;
+	fw_max_addr = 0;
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		const struct elf32_phdr *phdr = &phdrs[i];
+
+		if (!_check_segment(phdr))
+			continue;
+
+		fw_min_addr = min_t(phys_addr_t, fw_min_addr, phdr->p_paddr);
+		fw_max_addr = max_t(phys_addr_t, fw_max_addr,
+			PAGE_ALIGN(phdr->p_paddr + phdr->p_memsz));
+	}
+
+	if (fw_min_addr == (phys_addr_t) ULLONG_MAX && fw_max_addr == 0)
+		goto out;
+
+	fw_size = (size_t) (fw_max_addr - fw_min_addr);
+
+	/* Verify the MDT header */
+	ret = qcom_scm_pas_init_image(pas_id, mdt->data, mdt->size);
+	if (ret) {
+		dev_err(&pdev->dev, "Invalid firmware metadata\n");
+		goto out;
+	}
+
+	/* allocate some memory */
+	ptr = dma_alloc_coherent(&pdev->dev, fw_size, &fw_phys, GFP_KERNEL);
+	if (ptr == NULL)
+		goto out;
+
+	/* Set up the newly allocated memory region */
+	ret = qcom_scm_pas_mem_setup(pas_id, fw_phys, fw_size);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to set up firmware memory\n");
+		goto out;
+	}
+
+	ret = __pil_tz_load_image(pdev, mdt, fwname, ptr, fw_size, fw_min_addr);
+	if (!ret) {
+		ret = qcom_scm_pas_auth_and_reset(pas_id);
+		if (ret)
+			dev_err(&pdev->dev, "Unable to authorize the image\n");
+	}
+
+out:
+	if (ret && ptr)
+		dma_free_coherent(&pdev->dev, fw_size, ptr, fw_phys);
+
+	release_firmware(mdt);
+	return ret;
+}
+
 static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 	struct msm_file_private *ctx)
 {
-- 
1.9.1

_______________________________________________
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno

  parent reply	other threads:[~2016-11-04 22:44 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-04 22:44 [RFC] Initial support for the Adreno A5XX Jordan Crouse
     [not found] ` <1478299497-9729-1-git-send-email-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2016-11-04 22:44   ` [PATCH 01/16] drm/msm: Remove dependency on COMMON_CLK Jordan Crouse
2016-11-04 22:44   ` [PATCH 02/16] drm/msm: Rename the MSM driver so it doesn't conflict with other drivers Jordan Crouse
2016-11-04 22:44   ` [PATCH 03/16] drm/msm: gpu: Cut down the list of "generic" registers to the ones we use Jordan Crouse
2016-11-04 22:44   ` [PATCH 04/16] drm: msm: Flush the cache immediately after allocating pages Jordan Crouse
2016-11-06 14:15     ` [Freedreno] " Rob Clark
     [not found]       ` <CAF6AEGtDv8tRZi82Eno5RF6a58qSRpjYcUo-J8dDDioDLLJqmg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-11-07  8:35         ` Archit Taneja
     [not found]           ` <99a66f0f-ec84-a26e-0108-60367362c29e-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2016-11-07 12:19             ` Rob Clark
2016-11-07 18:01               ` [Freedreno] " Jordan Crouse
2016-11-04 22:44   ` [PATCH 05/16] drm/msm: gpu: Return error on hw_init failure Jordan Crouse
     [not found]     ` <1478299497-9729-6-git-send-email-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2016-11-07 18:54       ` Rob Clark
2016-11-04 22:44   ` [PATCH 06/16] drm/msm: gpu: Add OUT_TYPE4 and OUT_TYPE7 Jordan Crouse
2016-11-04 22:44   ` [PATCH 07/16] drm/msm: Add adreno_gpu_write64() Jordan Crouse
2016-11-07 19:19     ` [Freedreno] " Rob Clark
2016-11-04 22:44   ` [PATCH 08/16] drm/msm: Remove 'src_clk' from adreno configuration Jordan Crouse
2016-11-04 22:44   ` [PATCH 09/16] drm/msm: gpu Add new gpu register read/write functions Jordan Crouse
     [not found]     ` <1478299497-9729-10-git-send-email-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2016-11-07 19:17       ` Rob Clark
2016-11-04 22:44   ` [PATCH 10/16] drm/msm: Disable interrupts during init Jordan Crouse
2016-11-04 22:44   ` [PATCH 13/16] drm/msm: gpu: Add support for the GPMU Jordan Crouse
     [not found]     ` <1478299497-9729-14-git-send-email-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2016-11-07 12:58       ` Stanimir Varbanov
2016-11-07 13:02         ` [Freedreno] " Rob Clark
     [not found]           ` <CAF6AEGuW6ThJM-+X-=XGtqTCY_hcq8DghJHRf38OWjy4Z3R=DQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-11-07 14:47             ` Stanimir Varbanov
     [not found]         ` <740c4fda-dfd6-7a70-9cb7-3eec6a5781ca-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-11-07 18:09           ` Jordan Crouse
2016-11-04 22:44   ` Jordan Crouse [this message]
2016-11-04 22:44   ` [PATCH 16/16] drm/msm: gpu: Use the zap shader on 5XX if we can Jordan Crouse
2016-11-04 22:44 ` [PATCH 11/16] arm64: dts: Add Adreno GPU and GPU smmu definitions Jordan Crouse
2016-11-04 22:44 ` [PATCH 12/16] drm/msm: gpu: Add A5XX target support Jordan Crouse
2016-11-04 22:44 ` [PATCH 14/16] firmware: qcom_scm: Add qcom_scm_gpu_zap_resume() Jordan Crouse
2016-11-08 17:12 ` [Freedreno] [RFC] Initial support for the Adreno A5XX Jordan Crouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1478299497-9729-16-git-send-email-jcrouse@codeaurora.org \
    --to=jcrouse-sgv2jx0feol9jmxxk+q4oq@public.gmane.org \
    --cc=freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org \
    --cc=linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.