[4/6] remoteproc: mtk_vpu_rproc: Don't try to load empty PT_LOAD segment
diff mbox series

Message ID 20200713132927.24925-5-abailon@baylibre.com
State New
Headers show
Series
  • Add support of mt8183 APU
Related show

Commit Message

Alexandre Bailon July 13, 2020, 1:29 p.m. UTC
The firmware generated by our toolchain contains many empty PT_LOAD
segments. The elf loader don't manage it and will raise an error:
"bad phdr da 0x0 mem 0x0".
To workaround it, implement the sanity_check callback to detect the
empty PT_LOAD segment and change it to PT_NULL.
In that way, the elf load won't try to load the segment.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
---
 drivers/remoteproc/mtk_apu_rproc.c | 35 +++++++++++++++++++++++++++---
 1 file changed, 32 insertions(+), 3 deletions(-)

Comments

Mathieu Poirier July 21, 2020, 8:21 p.m. UTC | #1
On Mon, Jul 13, 2020 at 03:29:25PM +0200, Alexandre Bailon wrote:
> The firmware generated by our toolchain contains many empty PT_LOAD
> segments. The elf loader don't manage it and will raise an error:
> "bad phdr da 0x0 mem 0x0".
> To workaround it, implement the sanity_check callback to detect the
> empty PT_LOAD segment and change it to PT_NULL.
> In that way, the elf load won't try to load the segment.

This patch doesn't address the real problem, which are empty load segments.  In
my opinion that should be dealt with rather than having to patch things up.  On
the flip side I suspect that you don't control all the process and that systems
are out there with faulty fw images.  As such:

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

> 
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
> ---
>  drivers/remoteproc/mtk_apu_rproc.c | 35 +++++++++++++++++++++++++++---
>  1 file changed, 32 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/remoteproc/mtk_apu_rproc.c b/drivers/remoteproc/mtk_apu_rproc.c
> index f2342b747a35..565b3adca5de 100644
> --- a/drivers/remoteproc/mtk_apu_rproc.c
> +++ b/drivers/remoteproc/mtk_apu_rproc.c
> @@ -137,10 +137,39 @@ static void mtk_vpu_rproc_kick(struct rproc *rproc, int vqid)
>  	vpu_write32(vpu_rproc, CORE_CTL_XTENSA_INT, 1 << vqid);
>  }
>  
> +int mtk_vpu_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
> +{
> +	const u8 *elf_data = fw->data;
> +	struct elf32_hdr *ehdr;
> +	struct elf32_phdr *phdr;
> +	int ret;
> +	int i;
> +
> +	ret = rproc_elf_sanity_check(rproc, fw);
> +	if (ret)
> +		return ret;
> +
> +	ehdr = (struct elf32_hdr *)elf_data;
> +	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
> +
> +	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
> +		/* Remove empty PT_LOAD section */
> +		if (phdr->p_type == PT_LOAD && !phdr->p_paddr)
> +			phdr->p_type = PT_NULL;
> +	}
> +
> +	return 0;
> +}
> +
>  static const struct rproc_ops mtk_vpu_rproc_ops = {
> -	.start		= mtk_vpu_rproc_start,
> -	.stop		= mtk_vpu_rproc_stop,
> -	.kick		= mtk_vpu_rproc_kick,
> +	.start			= mtk_vpu_rproc_start,
> +	.stop			= mtk_vpu_rproc_stop,
> +	.kick			= mtk_vpu_rproc_kick,
> +	.load			= rproc_elf_load_segments,
> +	.parse_fw		= rproc_elf_load_rsc_table,
> +	.find_loaded_rsc_table	= rproc_elf_find_loaded_rsc_table,
> +	.sanity_check		= mtk_vpu_elf_sanity_check,
> +	.get_boot_addr		= rproc_elf_get_boot_addr,
>  };
>  
>  static irqreturn_t mtk_vpu_rproc_callback(int irq, void *data)
> -- 
> 2.26.2
>

Patch
diff mbox series

diff --git a/drivers/remoteproc/mtk_apu_rproc.c b/drivers/remoteproc/mtk_apu_rproc.c
index f2342b747a35..565b3adca5de 100644
--- a/drivers/remoteproc/mtk_apu_rproc.c
+++ b/drivers/remoteproc/mtk_apu_rproc.c
@@ -137,10 +137,39 @@  static void mtk_vpu_rproc_kick(struct rproc *rproc, int vqid)
 	vpu_write32(vpu_rproc, CORE_CTL_XTENSA_INT, 1 << vqid);
 }
 
+int mtk_vpu_elf_sanity_check(struct rproc *rproc, const struct firmware *fw)
+{
+	const u8 *elf_data = fw->data;
+	struct elf32_hdr *ehdr;
+	struct elf32_phdr *phdr;
+	int ret;
+	int i;
+
+	ret = rproc_elf_sanity_check(rproc, fw);
+	if (ret)
+		return ret;
+
+	ehdr = (struct elf32_hdr *)elf_data;
+	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
+
+	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+		/* Remove empty PT_LOAD section */
+		if (phdr->p_type == PT_LOAD && !phdr->p_paddr)
+			phdr->p_type = PT_NULL;
+	}
+
+	return 0;
+}
+
 static const struct rproc_ops mtk_vpu_rproc_ops = {
-	.start		= mtk_vpu_rproc_start,
-	.stop		= mtk_vpu_rproc_stop,
-	.kick		= mtk_vpu_rproc_kick,
+	.start			= mtk_vpu_rproc_start,
+	.stop			= mtk_vpu_rproc_stop,
+	.kick			= mtk_vpu_rproc_kick,
+	.load			= rproc_elf_load_segments,
+	.parse_fw		= rproc_elf_load_rsc_table,
+	.find_loaded_rsc_table	= rproc_elf_find_loaded_rsc_table,
+	.sanity_check		= mtk_vpu_elf_sanity_check,
+	.get_boot_addr		= rproc_elf_get_boot_addr,
 };
 
 static irqreturn_t mtk_vpu_rproc_callback(int irq, void *data)