linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware
@ 2019-06-22  1:21 Bjorn Andersson
  2019-06-22  1:21 ` [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images Bjorn Andersson
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Bjorn Andersson @ 2019-06-22  1:21 UTC (permalink / raw)
  To: Andy Gross, Ohad Ben-Cohen, Bjorn Andersson, Sibi Sankar
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel

Typically the firmware files for the various remoteprocs is split in a number
of files. But in some releases these files are available in their unsplit form.

Extend the mdt loader to detect the unsplit firmware and load it transparently.

Also expose the function that compose the metadata header for validation and
use this from the modem remoteproc driver, so that it can support unsplit files
as well.

Bjorn Andersson (2):
  soc: qcom: mdt_loader: Support loading non-split images
  remoteproc: qcom: q6v5-mss: Support loading non-split images

 drivers/remoteproc/qcom_q6v5_mss.c  | 33 ++++++++---
 drivers/soc/qcom/mdt_loader.c       | 88 ++++++++++++++++++++++++++++-
 include/linux/soc/qcom/mdt_loader.h |  2 +
 3 files changed, 112 insertions(+), 11 deletions(-)

-- 
2.18.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images
  2019-06-22  1:21 [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware Bjorn Andersson
@ 2019-06-22  1:21 ` Bjorn Andersson
  2019-07-01 14:38   ` Jeffrey Hugo
  2019-07-01 19:38   ` Andy Gross
  2019-06-22  1:21 ` [PATCH 2/2] remoteproc: qcom: q6v5-mss: " Bjorn Andersson
  2019-07-02  2:04 ` [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware Bjorn Andersson
  2 siblings, 2 replies; 7+ messages in thread
From: Bjorn Andersson @ 2019-06-22  1:21 UTC (permalink / raw)
  To: Andy Gross, Ohad Ben-Cohen, Bjorn Andersson, Sibi Sankar
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel

In some software releases the firmware images are not split up with each
loadable segment in it's own file. Check the size of the loaded firmware
to see if it still contains each segment to be loaded, before falling
back to the split-out segments.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/soc/qcom/mdt_loader.c       | 88 ++++++++++++++++++++++++++++-
 include/linux/soc/qcom/mdt_loader.h |  2 +
 2 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 9ca7d9484de0..24cd193dec55 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -66,6 +66,66 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw)
 }
 EXPORT_SYMBOL_GPL(qcom_mdt_get_size);
 
+/**
+ * qcom_mdt_read_metadata() - read header and metadata from mdt or mbn
+ * @fw:		firmware of mdt header or mbn
+ * @data_len:	length of the read metadata blob
+ *
+ * The mechanism that performs the authentication of the loading firmware
+ * expects an ELF header directly followed by the segment of hashes, with no
+ * padding inbetween. This function allocates a chunk of memory for this pair
+ * and copy the two pieces into the buffer.
+ *
+ * In the case of split firmware the hash is found directly following the ELF
+ * header, rather than at p_offset described by the second program header.
+ *
+ * The caller is responsible to free (kfree()) the returned pointer.
+ *
+ * Return: pointer to data, or ERR_PTR()
+ */
+void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len)
+{
+	const struct elf32_phdr *phdrs;
+	const struct elf32_hdr *ehdr;
+	size_t hash_offset;
+	size_t hash_size;
+	size_t ehdr_size;
+	void *data;
+
+	ehdr = (struct elf32_hdr *)fw->data;
+	phdrs = (struct elf32_phdr *)(ehdr + 1);
+
+	if (ehdr->e_phnum < 2)
+		return ERR_PTR(-EINVAL);
+
+	if (phdrs[0].p_type == PT_LOAD || phdrs[1].p_type == PT_LOAD)
+		return ERR_PTR(-EINVAL);
+
+	if ((phdrs[1].p_flags & QCOM_MDT_TYPE_MASK) != QCOM_MDT_TYPE_HASH)
+		return ERR_PTR(-EINVAL);
+
+	ehdr_size = phdrs[0].p_filesz;
+	hash_size = phdrs[1].p_filesz;
+
+	data = kmalloc(ehdr_size + hash_size, GFP_KERNEL);
+	if (!data)
+		return ERR_PTR(-ENOMEM);
+
+	/* Is the header and hash already packed */
+	if (ehdr_size + hash_size == fw->size)
+		hash_offset = phdrs[0].p_filesz;
+	else
+		hash_offset = phdrs[1].p_offset;
+
+	memcpy(data, fw->data, ehdr_size);
+	memcpy(data + ehdr_size, fw->data + hash_offset, hash_size);
+
+	*data_len = ehdr_size + hash_size;
+
+	return data;
+}
+EXPORT_SYMBOL_GPL(qcom_mdt_read_metadata);
+
 static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
 			   const char *firmware, int pas_id, void *mem_region,
 			   phys_addr_t mem_phys, size_t mem_size,
@@ -78,12 +138,14 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
 	phys_addr_t mem_reloc;
 	phys_addr_t min_addr = PHYS_ADDR_MAX;
 	phys_addr_t max_addr = 0;
+	size_t metadata_len;
 	size_t fw_name_len;
 	ssize_t offset;
+	void *metadata;
 	char *fw_name;
 	bool relocate = false;
 	void *ptr;
-	int ret;
+	int ret = 0;
 	int i;
 
 	if (!fw || !mem_region || !mem_phys || !mem_size)
@@ -101,7 +163,15 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
 		return -ENOMEM;
 
 	if (pas_init) {
-		ret = qcom_scm_pas_init_image(pas_id, fw->data, fw->size);
+		metadata = qcom_mdt_read_metadata(fw, &metadata_len);
+		if (IS_ERR(metadata)) {
+			ret = PTR_ERR(metadata);
+			goto out;
+		}
+
+		ret = qcom_scm_pas_init_image(pas_id, metadata, metadata_len);
+
+		kfree(metadata);
 		if (ret) {
 			dev_err(dev, "invalid firmware metadata\n");
 			goto out;
@@ -162,7 +232,19 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
 
 		ptr = mem_region + offset;
 
-		if (phdr->p_filesz) {
+		if (phdr->p_filesz && phdr->p_offset < fw->size) {
+			/* Firmware is large enough to be non-split */
+			if (phdr->p_offset + phdr->p_filesz > fw->size) {
+				dev_err(dev,
+					"failed to load segment %d from truncated file %s\n",
+					i, firmware);
+				ret = -EINVAL;
+				break;
+			}
+
+			memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz);
+		} else if (phdr->p_filesz) {
+			/* Firmware not large enough, load split-out segments */
 			sprintf(fw_name + fw_name_len - 3, "b%02d", i);
 			ret = request_firmware_into_buf(&seg_fw, fw_name, dev,
 							ptr, phdr->p_filesz);
diff --git a/include/linux/soc/qcom/mdt_loader.h b/include/linux/soc/qcom/mdt_loader.h
index 944b06aefb0f..e600baec6825 100644
--- a/include/linux/soc/qcom/mdt_loader.h
+++ b/include/linux/soc/qcom/mdt_loader.h
@@ -21,4 +21,6 @@ int qcom_mdt_load_no_init(struct device *dev, const struct firmware *fw,
 			  const char *fw_name, int pas_id, void *mem_region,
 			  phys_addr_t mem_phys, size_t mem_size,
 			  phys_addr_t *reloc_base);
+void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len);
+
 #endif
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] remoteproc: qcom: q6v5-mss: Support loading non-split images
  2019-06-22  1:21 [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware Bjorn Andersson
  2019-06-22  1:21 ` [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images Bjorn Andersson
@ 2019-06-22  1:21 ` Bjorn Andersson
  2019-07-01 14:39   ` Jeffrey Hugo
  2019-07-02  2:04 ` [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware Bjorn Andersson
  2 siblings, 1 reply; 7+ messages in thread
From: Bjorn Andersson @ 2019-06-22  1:21 UTC (permalink / raw)
  To: Andy Gross, Ohad Ben-Cohen, Bjorn Andersson, Sibi Sankar
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel

In some software releases the firmware images are not split up with each
loadable segment in it's own file. Check the size of the loaded firmware
to see if it still contains each segment to be loaded, before falling
back to the split-out segments.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/remoteproc/qcom_q6v5_mss.c | 33 ++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
index 981581bcdd56..8fcf9d28dd73 100644
--- a/drivers/remoteproc/qcom_q6v5_mss.c
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
@@ -659,23 +659,29 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
 {
 	unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
 	dma_addr_t phys;
+	void *metadata;
 	int mdata_perm;
 	int xferop_ret;
+	size_t size;
 	void *ptr;
 	int ret;
 
-	ptr = dma_alloc_attrs(qproc->dev, fw->size, &phys, GFP_KERNEL, dma_attrs);
+	metadata = qcom_mdt_read_metadata(fw, &size);
+	if (IS_ERR(metadata))
+		return PTR_ERR(metadata);
+
+	ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs);
 	if (!ptr) {
+		kfree(metadata);
 		dev_err(qproc->dev, "failed to allocate mdt buffer\n");
 		return -ENOMEM;
 	}
 
-	memcpy(ptr, fw->data, fw->size);
+	memcpy(ptr, metadata, size);
 
 	/* Hypervisor mapping to access metadata by modem */
 	mdata_perm = BIT(QCOM_SCM_VMID_HLOS);
-	ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
-				      true, phys, fw->size);
+	ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, true, phys, size);
 	if (ret) {
 		dev_err(qproc->dev,
 			"assigning Q6 access to metadata failed: %d\n", ret);
@@ -693,14 +699,14 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
 		dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);
 
 	/* Metadata authentication done, remove modem access */
-	xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm,
-					     false, phys, fw->size);
+	xferop_ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, false, phys, size);
 	if (xferop_ret)
 		dev_warn(qproc->dev,
 			 "mdt buffer not reclaimed system may become unstable\n");
 
 free_dma_attrs:
-	dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs);
+	dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs);
+	kfree(metadata);
 
 	return ret < 0 ? ret : 0;
 }
@@ -981,7 +987,18 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
 
 		ptr = qproc->mpss_region + offset;
 
-		if (phdr->p_filesz) {
+		if (phdr->p_filesz && phdr->p_offset < fw->size) {
+			/* Firmware is large enough to be non-split */
+			if (phdr->p_offset + phdr->p_filesz > fw->size) {
+				dev_err(qproc->dev,
+					"failed to load segment %d from truncated file %s\n",
+					i, fw_name);
+				ret = -EINVAL;
+				goto release_firmware;
+			}
+
+			memcpy(ptr, fw->data + phdr->p_offset, phdr->p_filesz);
+		} else if (phdr->p_filesz) {
 			/* Replace "xxx.xxx" with "xxx.bxx" */
 			sprintf(fw_name + fw_name_len - 3, "b%02d", i);
 			ret = request_firmware(&seg_fw, fw_name, qproc->dev);
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images
  2019-06-22  1:21 ` [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images Bjorn Andersson
@ 2019-07-01 14:38   ` Jeffrey Hugo
  2019-07-01 19:38   ` Andy Gross
  1 sibling, 0 replies; 7+ messages in thread
From: Jeffrey Hugo @ 2019-07-01 14:38 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Andy Gross, Ohad Ben-Cohen, Sibi Sankar, MSM, linux-remoteproc, lkml

On Fri, Jun 21, 2019 at 7:22 PM Bjorn Andersson
<bjorn.andersson@linaro.org> wrote:
>
> In some software releases the firmware images are not split up with each
> loadable segment in it's own file. Check the size of the loaded firmware
> to see if it still contains each segment to be loaded, before falling
> back to the split-out segments.
>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

Reviewed-by: Jeffrey Hugo <jeffrey.l.hugo@gmail.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] remoteproc: qcom: q6v5-mss: Support loading non-split images
  2019-06-22  1:21 ` [PATCH 2/2] remoteproc: qcom: q6v5-mss: " Bjorn Andersson
@ 2019-07-01 14:39   ` Jeffrey Hugo
  0 siblings, 0 replies; 7+ messages in thread
From: Jeffrey Hugo @ 2019-07-01 14:39 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Andy Gross, Ohad Ben-Cohen, Sibi Sankar, MSM, linux-remoteproc, lkml

On Fri, Jun 21, 2019 at 7:22 PM Bjorn Andersson
<bjorn.andersson@linaro.org> wrote:
>
> In some software releases the firmware images are not split up with each
> loadable segment in it's own file. Check the size of the loaded firmware
> to see if it still contains each segment to be loaded, before falling
> back to the split-out segments.
>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

Reviewed-by: Jeffrey Hugo <jeffrey.l.hugo@gmail.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images
  2019-06-22  1:21 ` [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images Bjorn Andersson
  2019-07-01 14:38   ` Jeffrey Hugo
@ 2019-07-01 19:38   ` Andy Gross
  1 sibling, 0 replies; 7+ messages in thread
From: Andy Gross @ 2019-07-01 19:38 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ohad Ben-Cohen, Sibi Sankar, linux-arm-msm, linux-remoteproc,
	linux-kernel

On Fri, Jun 21, 2019 at 06:21:45PM -0700, Bjorn Andersson wrote:
> In some software releases the firmware images are not split up with each
> loadable segment in it's own file. Check the size of the loaded firmware
> to see if it still contains each segment to be loaded, before falling
> back to the split-out segments.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

This looks fine to me.

Acked-by: Andy Gross <agross@kernel.org>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware
  2019-06-22  1:21 [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware Bjorn Andersson
  2019-06-22  1:21 ` [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images Bjorn Andersson
  2019-06-22  1:21 ` [PATCH 2/2] remoteproc: qcom: q6v5-mss: " Bjorn Andersson
@ 2019-07-02  2:04 ` Bjorn Andersson
  2 siblings, 0 replies; 7+ messages in thread
From: Bjorn Andersson @ 2019-07-02  2:04 UTC (permalink / raw)
  To: Andy Gross, Ohad Ben-Cohen, Sibi Sankar
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel

On Fri 21 Jun 18:21 PDT 2019, Bjorn Andersson wrote:

> Typically the firmware files for the various remoteprocs is split in a number
> of files. But in some releases these files are available in their unsplit form.
> 
> Extend the mdt loader to detect the unsplit firmware and load it transparently.
> 
> Also expose the function that compose the metadata header for validation and
> use this from the modem remoteproc driver, so that it can support unsplit files
> as well.
> 

Applied the two patches. Thanks Andy & Jeff.

Regards,
Bjorn

> Bjorn Andersson (2):
>   soc: qcom: mdt_loader: Support loading non-split images
>   remoteproc: qcom: q6v5-mss: Support loading non-split images
> 
>  drivers/remoteproc/qcom_q6v5_mss.c  | 33 ++++++++---
>  drivers/soc/qcom/mdt_loader.c       | 88 ++++++++++++++++++++++++++++-
>  include/linux/soc/qcom/mdt_loader.h |  2 +
>  3 files changed, 112 insertions(+), 11 deletions(-)
> 
> -- 
> 2.18.0
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-07-02  2:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-22  1:21 [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware Bjorn Andersson
2019-06-22  1:21 ` [PATCH 1/2] soc: qcom: mdt_loader: Support loading non-split images Bjorn Andersson
2019-07-01 14:38   ` Jeffrey Hugo
2019-07-01 19:38   ` Andy Gross
2019-06-22  1:21 ` [PATCH 2/2] remoteproc: qcom: q6v5-mss: " Bjorn Andersson
2019-07-01 14:39   ` Jeffrey Hugo
2019-07-02  2:04 ` [PATCH 0/2] soc: qcom: mdt_loader: Support loading non-split firmware Bjorn Andersson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).